diff --git a/source/jsffi.c b/source/jsffi.c index 03a3a0d8..5dd73298 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -170,33 +170,6 @@ typedef struct texture_vertex { uint8_t r, g, b,a; } texture_vertex; - -static inline size_t typed_array_bytes(JSTypedArrayEnum type) { - switch(type) { - case JS_TYPED_ARRAY_UINT8C: - case JS_TYPED_ARRAY_INT8: - case JS_TYPED_ARRAY_UINT8: - return 1; - - case JS_TYPED_ARRAY_INT16: - case JS_TYPED_ARRAY_UINT16: - return 2; - - case JS_TYPED_ARRAY_INT32: - case JS_TYPED_ARRAY_UINT32: - case JS_TYPED_ARRAY_FLOAT32: - return 4; - - case JS_TYPED_ARRAY_BIG_INT64: - case JS_TYPED_ARRAY_BIG_UINT64: - case JS_TYPED_ARRAY_FLOAT64: - return 8; - - default: - return 0; // Return 0 for unknown types - } -} - #define JS_GETNUM(JS,VAL,I,TO,TYPE) { \ JSValue val = JS_GetPropertyUint32(JS,VAL,I); \ TO = js2##TYPE(JS, val); \ @@ -274,23 +247,25 @@ JSValue make_gpu_buffer(JSContext *js, void *data, size_t size, int type, int el tstack[2] = JS_UNDEFINED; // TODO: always copying; implement "takeover" tstack[0] = js_new_blob_stoned_copy(js,data,size);//, make_gpu_buffer, NULL, 1); - JSValue ret = JS_NewTypedArray(js, 3, tstack, type); - JS_SetPropertyStr(js,ret,"stride", number2js(js,typed_array_bytes(type)*elements)); - JS_SetPropertyStr(js,ret,"elen", number2js(js,typed_array_bytes(type))); - JS_SetPropertyStr(js,ret,"index", JS_NewBool(js,index)); - JS_FreeValue(js,tstack[0]); - return ret; +// JSValue ret = JS_NewTypedArray(js, 3, tstack, type); +// JS_SetPropertyStr(js,ret,"stride", number2js(js,typed_array_bytes(type)*elements)); +// JS_SetPropertyStr(js,ret,"elen", number2js(js,typed_array_bytes(type))); +// JS_SetPropertyStr(js,ret,"index", JS_NewBool(js,index)); +// JS_FreeValue(js,tstack[0]); +// return ret; + return JS_UNDEFINED; } void *get_gpu_buffer(JSContext *js, JSValue argv, size_t *stride, size_t *size) { - size_t o, len, bytes, msize; + return NULL; +/* size_t o, len, bytes, msize; JSValue buf = JS_GetTypedArrayBuffer(js, argv, &o, &len, &bytes); void *data = js_get_blob_data(js, &msize, buf); JS_FreeValue(js,buf); if (stride) *stride = js_getnum_str(js, argv, "stride"); if (size) *size = msize; - return data; + return data;*/ } JSValue make_quad_indices_buffer(JSContext *js, int quads) @@ -314,7 +289,7 @@ JSValue make_quad_indices_buffer(JSContext *js, int quads) if (!JS_IsUndefined(rt->idx_buffer)) JS_FreeValue(js,rt->idx_buffer); - rt->idx_buffer = make_gpu_buffer(js,indices, sizeof(*indices)*count, JS_TYPED_ARRAY_UINT16, 1,0,1); +// rt->idx_buffer = make_gpu_buffer(js,indices, sizeof(*indices)*count, JS_TYPED_ARRAY_UINT16, 1,0,1); rt->idx_count = count; return JS_DupValue(js,rt->idx_buffer); } @@ -333,9 +308,9 @@ JSValue quads_to_mesh(JSContext *js, text_vert *buffer) color[i] = buffer[i].color; } - JSValue jspos = make_gpu_buffer(js, pos, sizeof(HMM_Vec2)*arrlen(buffer), JS_TYPED_ARRAY_FLOAT32, 2,0,0); - JSValue jsuv = make_gpu_buffer(js, uv, sizeof(HMM_Vec2)*arrlen(buffer), JS_TYPED_ARRAY_FLOAT32, 2,0,0); - JSValue jscolor = make_gpu_buffer(js, color, sizeof(HMM_Vec4)*arrlen(buffer), JS_TYPED_ARRAY_FLOAT32, 4,0,0); + JSValue jspos = make_gpu_buffer(js, pos, sizeof(HMM_Vec2)*arrlen(buffer), 0, 2,0,0); + JSValue jsuv = make_gpu_buffer(js, uv, sizeof(HMM_Vec2)*arrlen(buffer), 0, 2,0,0); + JSValue jscolor = make_gpu_buffer(js, color, sizeof(HMM_Vec4)*arrlen(buffer), 0, 4,0,0); size_t quads = verts/4; size_t count = verts/2*3; @@ -1239,10 +1214,12 @@ JSValue make_color_buffer(JSContext *js, colorf c, int verts) for (int i = 0; i < verts; i++) colordata[i] = c; - return make_gpu_buffer(js, colordata, sizeof(*colordata)*verts, JS_TYPED_ARRAY_FLOAT32, 4, 0, 0); + return make_gpu_buffer(js, colordata, sizeof(*colordata)*verts, 0, 4, 0, 0); } JSC_CCALL(os_make_line_prim, + return JS_UNDEFINED; + /* JSValue prim = JS_NewObject(js); HMM_Vec2 *v = js2cpvec2arr(js,argv[0]); @@ -1262,7 +1239,7 @@ JSC_CCALL(os_make_line_prim, .closed = JS_ToBool(js,argv[3]) }); - JS_SetPropertyStr(js, prim, "pos", make_gpu_buffer(js,m->positions,sizeof(*m->positions)*m->num_vertices, JS_TYPED_ARRAY_FLOAT32, 2,1,0)); + JS_SetPropertyStr(js, prim, "pos", make_gpu_buffer(js,m->positions,sizeof(*m->positions)*m->num_vertices, 0, 2,1,0)); JS_SetPropertyStr(js, prim, "indices", make_gpu_buffer(js,m->triangle_indices,sizeof(*m->triangle_indices)*m->num_triangles*3, JS_TYPED_ARRAY_UINT32, 1,1,1)); @@ -1272,7 +1249,7 @@ JSC_CCALL(os_make_line_prim, uv[i*2+1] = m->annotations[i].v_across_curve; } - JS_SetPropertyStr(js, prim, "uv", make_gpu_buffer(js, uv, sizeof(uv), JS_TYPED_ARRAY_FLOAT32,2,1,0)); + JS_SetPropertyStr(js, prim, "uv", make_gpu_buffer(js, uv, sizeof(uv), 0,2,1,0)); JS_SetPropertyStr(js,prim,"vertices", number2js(js,m->num_vertices)); JS_SetPropertyStr(js,prim,"color",make_color_buffer(js,js2color(js,argv[4]), m->num_vertices)); JS_SetPropertyStr(js,prim,"num_indices", number2js(js,m->num_triangles*3)); @@ -1281,6 +1258,7 @@ JSC_CCALL(os_make_line_prim, parsl_destroy_context(par_ctx); return prim; + */ ) static void render_frame(plm_t *mpeg, plm_frame_t *frame, datastream *ds) { diff --git a/source/qjs_geometry.c b/source/qjs_geometry.c index 3b8fdb00..bff791d4 100644 --- a/source/qjs_geometry.c +++ b/source/qjs_geometry.c @@ -529,9 +529,9 @@ JSC_CCALL(gpu_make_sprite_mesh, size_t uv_size = sizeof(*uvdata)*verts; size_t color_size = sizeof(*colordata)*verts; - BufferCheckResult pos_chk = get_or_extend_buffer(js, old_mesh, "pos", pos_size, JS_TYPED_ARRAY_FLOAT32, 2, 1, 0); - BufferCheckResult uv_chk = get_or_extend_buffer(js, old_mesh, "uv", uv_size, JS_TYPED_ARRAY_FLOAT32, 2, 1, 0); - BufferCheckResult color_chk = get_or_extend_buffer(js, old_mesh, "color", color_size, JS_TYPED_ARRAY_FLOAT32, 4, 1, 0); + BufferCheckResult pos_chk = get_or_extend_buffer(js, old_mesh, "pos", pos_size, 0, 2, 1, 0); + BufferCheckResult uv_chk = get_or_extend_buffer(js, old_mesh, "uv", uv_size, 0, 2, 1, 0); + BufferCheckResult color_chk = get_or_extend_buffer(js, old_mesh, "color", color_size, 0, 4, 1, 0); int need_new_all = pos_chk.need_new || uv_chk.need_new || color_chk.need_new; @@ -539,9 +539,9 @@ JSC_CCALL(gpu_make_sprite_mesh, if (need_new_all) { // Create all new buffers - JSValue new_pos = make_gpu_buffer(js, posdata, pos_size, JS_TYPED_ARRAY_FLOAT32, 2, 1,0); - JSValue new_uv = make_gpu_buffer(js, uvdata, uv_size, JS_TYPED_ARRAY_FLOAT32, 2, 1,0); - JSValue new_color = make_gpu_buffer(js, colordata, color_size, JS_TYPED_ARRAY_FLOAT32, 0, 1,0); + JSValue new_pos = make_gpu_buffer(js, posdata, pos_size, 0, 2, 1,0); + JSValue new_uv = make_gpu_buffer(js, uvdata, uv_size, 0, 2, 1,0); + JSValue new_color = make_gpu_buffer(js, colordata, color_size, 0, 0, 1,0); JS_SetPropertyStr(js, ret, "pos", new_pos); JS_SetPropertyStr(js, ret, "uv", new_uv); @@ -603,9 +603,9 @@ struct quad_buffers quad_buffers_new(int verts) JSValue quadbuffers_to_mesh(JSContext *js, struct quad_buffers buffers) { - JSValue jspos = make_gpu_buffer(js, buffers.pos, sizeof(HMM_Vec2)*buffers.verts, JS_TYPED_ARRAY_FLOAT32, 2, 0, 0); - JSValue jsuv = make_gpu_buffer(js, buffers.uv, sizeof(HMM_Vec2)*buffers.verts, JS_TYPED_ARRAY_FLOAT32, 2,0,0); - JSValue jscolor = make_gpu_buffer(js, buffers.color, sizeof(HMM_Vec4)*buffers.verts, JS_TYPED_ARRAY_FLOAT32, 4,0,0); + JSValue jspos = make_gpu_buffer(js, buffers.pos, sizeof(HMM_Vec2)*buffers.verts, 0, 2, 0, 0); + JSValue jsuv = make_gpu_buffer(js, buffers.uv, sizeof(HMM_Vec2)*buffers.verts, 0, 2,0,0); + JSValue jscolor = make_gpu_buffer(js, buffers.color, sizeof(HMM_Vec4)*buffers.verts, 0, 4,0,0); size_t quads = buffers.verts/4; size_t count = buffers.verts/2*3; diff --git a/source/qjs_miniz.c b/source/qjs_miniz.c index 83452169..6d1b9094 100644 --- a/source/qjs_miniz.c +++ b/source/qjs_miniz.c @@ -166,10 +166,10 @@ static JSValue js_miniz_decompress(JSContext *js, JSValue ret; int asString = (argc > 1) && JS_ToBool(js, argv[1]); - if (asString) +// if (asString) ret = JS_NewStringLen(js, (const char *)out_ptr, out_len); - else - ret = JS_NewArrayBufferCopy(js, out_ptr, out_len); +// else +// ret = JS_NewArrayBufferCopy(js, out_ptr, out_len); #ifdef MZ_FREE MZ_FREE(out_ptr); diff --git a/source/quickjs.c b/source/quickjs.c index 60420444..4ee51aa9 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -132,21 +132,6 @@ enum { JS_CLASS_C_FUNCTION_DATA, /* u.c_function_data_record */ JS_CLASS_FOR_IN_ITERATOR, /* u.for_in_iterator */ JS_CLASS_REGEXP, /* u.regexp */ - JS_CLASS_ARRAY_BUFFER, /* u.array_buffer */ - JS_CLASS_SHARED_ARRAY_BUFFER, /* u.array_buffer */ - JS_CLASS_UINT8C_ARRAY, /* u.array (typed_array) */ - JS_CLASS_INT8_ARRAY, /* u.array (typed_array) */ - JS_CLASS_UINT8_ARRAY, /* u.array (typed_array) */ - JS_CLASS_INT16_ARRAY, /* u.array (typed_array) */ - JS_CLASS_UINT16_ARRAY, /* u.array (typed_array) */ - JS_CLASS_INT32_ARRAY, /* u.array (typed_array) */ - JS_CLASS_UINT32_ARRAY, /* u.array (typed_array) */ - JS_CLASS_BIG_INT64_ARRAY, /* u.array (typed_array) */ - JS_CLASS_BIG_UINT64_ARRAY, /* u.array (typed_array) */ - JS_CLASS_FLOAT16_ARRAY, /* u.array (typed_array) */ - JS_CLASS_FLOAT32_ARRAY, /* u.array (typed_array) */ - JS_CLASS_FLOAT64_ARRAY, /* u.array (typed_array) */ - JS_CLASS_DATAVIEW, /* u.typed_array */ JS_CLASS_BIG_INT, /* u.object_data */ JS_CLASS_MAP, /* u.map_state */ JS_CLASS_SET, /* u.map_state */ @@ -164,11 +149,6 @@ enum { JS_CLASS_INIT_COUNT, /* last entry for predefined classes */ }; -/* number of typed array types */ -#define JS_TYPED_ARRAY_COUNT (JS_CLASS_FLOAT64_ARRAY - JS_CLASS_UINT8C_ARRAY + 1) -static uint8_t const typed_array_size_log2[JS_TYPED_ARRAY_COUNT]; -#define typed_array_size_log2(classid) (typed_array_size_log2[(classid)- JS_CLASS_UINT8C_ARRAY]) - typedef enum JSErrorEnum { JS_EVAL_ERROR, JS_RANGE_ERROR, @@ -260,9 +240,6 @@ struct JSRuntime { JSInterruptHandler *interrupt_handler; void *interrupt_opaque; - BOOL can_block : 8; /* TRUE if Atomics.wait can block */ - /* used to allocate, free and clone SharedArrayBuffers */ - JSSharedArrayBufferFunctions sab_funcs; /* see JS_SetStripInfo() */ uint8_t strip_flags; @@ -635,24 +612,6 @@ typedef struct JSProxyData { uint8_t is_revoked; } JSProxyData; -typedef struct JSArrayBuffer { - int byte_length; /* 0 if detached */ - uint8_t detached; - uint8_t shared; /* if shared, the array buffer cannot be detached */ - uint8_t *data; /* NULL if detached */ - struct list_head array_list; - void *opaque; - JSFreeArrayBufferDataFunc *free_func; -} JSArrayBuffer; - -typedef struct JSTypedArray { - struct list_head link; /* link to arraybuffer */ - JSObject *obj; /* back pointer to the TypedArray/DataView object */ - JSObject *buffer; /* based array buffer */ - uint32_t offset; /* offset in the array buffer */ - uint32_t length; /* length in the array buffer */ -} JSTypedArray; - typedef enum { /* binary operators */ JS_OVOP_ADD, @@ -778,8 +737,6 @@ struct JSObject { struct JSBoundFunction *bound_function; /* JS_CLASS_BOUND_FUNCTION */ struct JSCFunctionDataRecord *c_function_data_record; /* JS_CLASS_C_FUNCTION_DATA */ struct JSForInIterator *for_in_iterator; /* JS_CLASS_FOR_IN_ITERATOR */ - struct JSArrayBuffer *array_buffer; /* JS_CLASS_ARRAY_BUFFER, JS_CLASS_SHARED_ARRAY_BUFFER */ - struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_DATAVIEW */ struct JSMapState *map_state; /* JS_CLASS_MAP..JS_CLASS_WEAKSET */ struct JSMapIteratorData *map_iterator_data; /* JS_CLASS_MAP_ITERATOR, JS_CLASS_SET_ITERATOR */ struct JSArrayIteratorData *array_iterator_data; /* JS_CLASS_ARRAY_ITERATOR, JS_CLASS_STRING_ITERATOR */ @@ -800,22 +757,9 @@ struct JSObject { struct { /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ union { uint32_t size; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ - struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ } u1; union { JSValue *values; /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ - void *ptr; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */ - int8_t *int8_ptr; /* JS_CLASS_INT8_ARRAY */ - uint8_t *uint8_ptr; /* JS_CLASS_UINT8_ARRAY, JS_CLASS_UINT8C_ARRAY */ - int16_t *int16_ptr; /* JS_CLASS_INT16_ARRAY */ - uint16_t *uint16_ptr; /* JS_CLASS_UINT16_ARRAY */ - int32_t *int32_ptr; /* JS_CLASS_INT32_ARRAY */ - uint32_t *uint32_ptr; /* JS_CLASS_UINT32_ARRAY */ - int64_t *int64_ptr; /* JS_CLASS_INT64_ARRAY */ - uint64_t *uint64_ptr; /* JS_CLASS_UINT64_ARRAY */ - uint16_t *fp16_ptr; /* JS_CLASS_FLOAT16_ARRAY */ - float *float_ptr; /* JS_CLASS_FLOAT32_ARRAY */ - double *double_ptr; /* JS_CLASS_FLOAT64_ARRAY */ } u; uint32_t count; /* <= 2^31-1. 0 for a detached typed array */ } array; /* 12/20 bytes */ @@ -945,10 +889,6 @@ static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val); static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); static void js_regexp_finalizer(JSRuntime *rt, JSValue val); -static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val); -static void js_typed_array_finalizer(JSRuntime *rt, JSValue val); -static void js_typed_array_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func); static void js_proxy_finalizer(JSRuntime *rt, JSValue val); static void js_proxy_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); @@ -1010,24 +950,6 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p, int flags); static int js_string_memcmp(const JSString *p1, int pos1, const JSString *p2, int pos2, int len); -static JSValue js_array_buffer_constructor3(JSContext *ctx, - JSValueConst new_target, - uint64_t len, JSClassID class_id, - uint8_t *buf, - JSFreeArrayBufferDataFunc *free_func, - void *opaque, BOOL alloc_flag); -static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj); -static JSValue js_typed_array_constructor(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv, - int classid); -static JSValue js_typed_array_constructor_ta(JSContext *ctx, - JSValueConst new_target, - JSValueConst src_obj, - int classid); -static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p); -static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p); -static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx); static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx, BOOL is_arg); static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, @@ -1292,21 +1214,6 @@ static JSClassShortDef const js_std_class_def[] = { { JS_ATOM_Function, js_c_function_data_finalizer, js_c_function_data_mark }, /* JS_CLASS_C_FUNCTION_DATA */ { JS_ATOM_ForInIterator, js_for_in_iterator_finalizer, js_for_in_iterator_mark }, /* JS_CLASS_FOR_IN_ITERATOR */ { JS_ATOM_RegExp, js_regexp_finalizer, NULL }, /* JS_CLASS_REGEXP */ - { JS_ATOM_ArrayBuffer, js_array_buffer_finalizer, NULL }, /* JS_CLASS_ARRAY_BUFFER */ - { JS_ATOM_SharedArrayBuffer, js_array_buffer_finalizer, NULL }, /* JS_CLASS_SHARED_ARRAY_BUFFER */ - { JS_ATOM_Uint8ClampedArray, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT8C_ARRAY */ - { JS_ATOM_Int8Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_INT8_ARRAY */ - { JS_ATOM_Uint8Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT8_ARRAY */ - { JS_ATOM_Int16Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_INT16_ARRAY */ - { JS_ATOM_Uint16Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT16_ARRAY */ - { JS_ATOM_Int32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_INT32_ARRAY */ - { JS_ATOM_Uint32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT32_ARRAY */ - { JS_ATOM_BigInt64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_INT64_ARRAY */ - { JS_ATOM_BigUint64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_UINT64_ARRAY */ - { JS_ATOM_Float16Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT16_ARRAY */ - { JS_ATOM_Float32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT32_ARRAY */ - { JS_ATOM_Float64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT64_ARRAY */ - { JS_ATOM_DataView, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_DATAVIEW */ { JS_ATOM_BigInt, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_INT */ { JS_ATOM_Map, js_map_finalizer, js_map_mark }, /* JS_CLASS_MAP */ { JS_ATOM_Set, js_map_finalizer, js_map_mark }, /* JS_CLASS_SET */ @@ -1537,17 +1444,6 @@ void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque) rt->interrupt_opaque = opaque; } -void JS_SetCanBlock(JSRuntime *rt, BOOL can_block) -{ - rt->can_block = can_block; -} - -void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, - const JSSharedArrayBufferFunctions *sf) -{ - rt->sab_funcs = *sf; -} - void JS_SetStripInfo(JSRuntime *rt, int flags) { rt->strip_flags = flags; @@ -1846,7 +1742,7 @@ JSContext *JS_NewContext(JSRuntime *rt) JS_AddIntrinsicJSON(ctx); JS_AddIntrinsicProxy(ctx); JS_AddIntrinsicMapSet(ctx); - JS_AddIntrinsicTypedArrays(ctx); + return ctx; } @@ -4788,25 +4684,8 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas p->prop[0].u.value = JS_UNDEFINED; break; case JS_CLASS_ARGUMENTS: - case JS_CLASS_UINT8C_ARRAY: - case JS_CLASS_INT8_ARRAY: - case JS_CLASS_UINT8_ARRAY: - case JS_CLASS_INT16_ARRAY: - case JS_CLASS_UINT16_ARRAY: - case JS_CLASS_INT32_ARRAY: - case JS_CLASS_UINT32_ARRAY: - case JS_CLASS_BIG_INT64_ARRAY: - case JS_CLASS_BIG_UINT64_ARRAY: - case JS_CLASS_FLOAT16_ARRAY: - case JS_CLASS_FLOAT32_ARRAY: - case JS_CLASS_FLOAT64_ARRAY: p->is_exotic = 1; p->fast_array = 1; - p->u.array.u.ptr = NULL; - p->u.array.count = 0; - break; - case JS_CLASS_DATAVIEW: - p->u.array.u.ptr = NULL; p->u.array.count = 0; break; case JS_CLASS_NUMBER: @@ -6061,33 +5940,6 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) } } break; - case JS_CLASS_ARRAY_BUFFER: /* u.array_buffer */ - case JS_CLASS_SHARED_ARRAY_BUFFER: /* u.array_buffer */ - { - JSArrayBuffer *abuf = p->u.array_buffer; - if (abuf) { - s->memory_used_count += 1; - s->memory_used_size += sizeof(*abuf); - if (abuf->data) { - s->memory_used_count += 1; - s->memory_used_size += abuf->byte_length; - } - } - } - break; - case JS_CLASS_UINT8C_ARRAY: /* u.typed_array / u.array */ - case JS_CLASS_INT8_ARRAY: /* u.typed_array / u.array */ - case JS_CLASS_UINT8_ARRAY: /* u.typed_array / u.array */ - case JS_CLASS_INT16_ARRAY: /* u.typed_array / u.array */ - case JS_CLASS_UINT16_ARRAY: /* u.typed_array / u.array */ - case JS_CLASS_INT32_ARRAY: /* u.typed_array / u.array */ - case JS_CLASS_UINT32_ARRAY: /* u.typed_array / u.array */ - case JS_CLASS_BIG_INT64_ARRAY: /* u.typed_array / u.array */ - case JS_CLASS_BIG_UINT64_ARRAY: /* u.typed_array / u.array */ - case JS_CLASS_FLOAT16_ARRAY: /* u.typed_array / u.array */ - case JS_CLASS_FLOAT32_ARRAY: /* u.typed_array / u.array */ - case JS_CLASS_FLOAT64_ARRAY: /* u.typed_array / u.array */ - case JS_CLASS_DATAVIEW: /* u.typed_array */ case JS_CLASS_MAP: /* u.map_state */ case JS_CLASS_SET: /* u.map_state */ case JS_CLASS_WEAKMAP: /* u.map_state */ @@ -7182,20 +7034,8 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, if (idx < p->u.array.count) { /* we avoid duplicating the code */ return JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx); - } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_FLOAT64_ARRAY) { - return JS_UNDEFINED; } - } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_FLOAT64_ARRAY) { - int ret; - ret = JS_AtomIsNumericIndex(ctx, prop); - if (ret != 0) { - if (ret < 0) - return JS_EXCEPTION; - return JS_UNDEFINED; - } - } + } } else { const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; if (em) { @@ -7755,15 +7595,6 @@ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); if (ret != 0) return ret; - if (p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_FLOAT64_ARRAY) { - ret = JS_AtomIsNumericIndex(ctx, prop); - if (ret != 0) { - if (ret < 0) - return -1; - return FALSE; - } - } p = p->shape->proto; if (!p) break; @@ -7823,40 +7654,6 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj, case JS_CLASS_ARGUMENTS: if (unlikely(idx >= p->u.array.count)) goto slow_path; return JS_DupValue(ctx, p->u.array.u.values[idx]); - case JS_CLASS_INT8_ARRAY: - if (unlikely(idx >= p->u.array.count)) goto slow_path; - return JS_NewInt32(ctx, p->u.array.u.int8_ptr[idx]); - case JS_CLASS_UINT8C_ARRAY: - case JS_CLASS_UINT8_ARRAY: - if (unlikely(idx >= p->u.array.count)) goto slow_path; - return JS_NewInt32(ctx, p->u.array.u.uint8_ptr[idx]); - case JS_CLASS_INT16_ARRAY: - if (unlikely(idx >= p->u.array.count)) goto slow_path; - return JS_NewInt32(ctx, p->u.array.u.int16_ptr[idx]); - case JS_CLASS_UINT16_ARRAY: - if (unlikely(idx >= p->u.array.count)) goto slow_path; - return JS_NewInt32(ctx, p->u.array.u.uint16_ptr[idx]); - case JS_CLASS_INT32_ARRAY: - if (unlikely(idx >= p->u.array.count)) goto slow_path; - return JS_NewInt32(ctx, p->u.array.u.int32_ptr[idx]); - case JS_CLASS_UINT32_ARRAY: - if (unlikely(idx >= p->u.array.count)) goto slow_path; - return JS_NewUint32(ctx, p->u.array.u.uint32_ptr[idx]); - case JS_CLASS_BIG_INT64_ARRAY: - if (unlikely(idx >= p->u.array.count)) goto slow_path; - return JS_NewBigInt64(ctx, p->u.array.u.int64_ptr[idx]); - case JS_CLASS_BIG_UINT64_ARRAY: - if (unlikely(idx >= p->u.array.count)) goto slow_path; - return JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]); - case JS_CLASS_FLOAT16_ARRAY: - if (unlikely(idx >= p->u.array.count)) goto slow_path; - return __JS_NewFloat64(ctx, fromfp16(p->u.array.u.fp16_ptr[idx])); - case JS_CLASS_FLOAT32_ARRAY: - if (unlikely(idx >= p->u.array.count)) goto slow_path; - return __JS_NewFloat64(ctx, p->u.array.u.float_ptr[idx]); - case JS_CLASS_FLOAT64_ARRAY: - if (unlikely(idx >= p->u.array.count)) goto slow_path; - return __JS_NewFloat64(ctx, p->u.array.u.double_ptr[idx]); default: goto slow_path; } @@ -8404,36 +8201,6 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val, flags); else break; - } else if (p1->class_id >= JS_CLASS_UINT8C_ARRAY && - p1->class_id <= JS_CLASS_FLOAT64_ARRAY) { - goto typed_array_oob; - } - } else if (p1->class_id >= JS_CLASS_UINT8C_ARRAY && - p1->class_id <= JS_CLASS_FLOAT64_ARRAY) { - ret = JS_AtomIsNumericIndex(ctx, prop); - if (ret != 0) { - if (ret < 0) { - JS_FreeValue(ctx, val); - return -1; - } - typed_array_oob: - if (p == p1) { - /* must convert the argument even if out of bound access */ - if (p1->class_id == JS_CLASS_BIG_INT64_ARRAY || - p1->class_id == JS_CLASS_BIG_UINT64_ARRAY) { - int64_t v; - if (JS_ToBigInt64Free(ctx, &v, val)) - return -1; - } else { - val = JS_ToNumberFree(ctx, val); - JS_FreeValue(ctx, val); - if (JS_IsException(val)) - return -1; - } - } else { - JS_FreeValue(ctx, val); - } - return TRUE; } } } else { @@ -8642,74 +8409,6 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, goto slow_path; set_value(ctx, &p->u.array.u.values[idx], val); break; - case JS_CLASS_UINT8C_ARRAY: - if (JS_ToUint8ClampFree(ctx, &v, val)) - return -1; - /* Note: the conversion can detach the typed array, so the - array bound check must be done after */ - if (unlikely(idx >= (uint32_t)p->u.array.count)) - goto ta_out_of_bound; - p->u.array.u.uint8_ptr[idx] = v; - break; - case JS_CLASS_INT8_ARRAY: - case JS_CLASS_UINT8_ARRAY: - if (JS_ToInt32Free(ctx, &v, val)) - return -1; - if (unlikely(idx >= (uint32_t)p->u.array.count)) - goto ta_out_of_bound; - p->u.array.u.uint8_ptr[idx] = v; - break; - case JS_CLASS_INT16_ARRAY: - case JS_CLASS_UINT16_ARRAY: - if (JS_ToInt32Free(ctx, &v, val)) - return -1; - if (unlikely(idx >= (uint32_t)p->u.array.count)) - goto ta_out_of_bound; - p->u.array.u.uint16_ptr[idx] = v; - break; - case JS_CLASS_INT32_ARRAY: - case JS_CLASS_UINT32_ARRAY: - if (JS_ToInt32Free(ctx, &v, val)) - return -1; - if (unlikely(idx >= (uint32_t)p->u.array.count)) - goto ta_out_of_bound; - p->u.array.u.uint32_ptr[idx] = v; - break; - case JS_CLASS_BIG_INT64_ARRAY: - case JS_CLASS_BIG_UINT64_ARRAY: - /* XXX: need specific conversion function */ - { - int64_t v; - if (JS_ToBigInt64Free(ctx, &v, val)) - return -1; - if (unlikely(idx >= (uint32_t)p->u.array.count)) - goto ta_out_of_bound; - p->u.array.u.uint64_ptr[idx] = v; - } - break; - case JS_CLASS_FLOAT16_ARRAY: - if (JS_ToFloat64Free(ctx, &d, val)) - return -1; - if (unlikely(idx >= (uint32_t)p->u.array.count)) - goto ta_out_of_bound; - p->u.array.u.fp16_ptr[idx] = tofp16(d); - break; - case JS_CLASS_FLOAT32_ARRAY: - if (JS_ToFloat64Free(ctx, &d, val)) - return -1; - if (unlikely(idx >= (uint32_t)p->u.array.count)) - goto ta_out_of_bound; - p->u.array.u.float_ptr[idx] = d; - break; - case JS_CLASS_FLOAT64_ARRAY: - if (JS_ToFloat64Free(ctx, &d, val)) - return -1; - if (unlikely(idx >= (uint32_t)p->u.array.count)) { - ta_out_of_bound: - return TRUE; - } - p->u.array.u.double_ptr[idx] = d; - break; default: goto slow_path; } @@ -8837,14 +8536,6 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p, set_value(ctx, &plen->u.value, JS_NewUint32(ctx, len)); } } - } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_FLOAT64_ARRAY) { - ret = JS_AtomIsNumericIndex(ctx, prop); - if (ret != 0) { - if (ret < 0) - return -1; - return JS_ThrowTypeErrorOrFalse(ctx, flags, "cannot create numeric index in typed array"); - } } else if (!(flags & JS_PROP_NO_EXOTIC)) { const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; if (em) { @@ -9196,52 +8887,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, return TRUE; } } - } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_FLOAT64_ARRAY) { - JSValue num; - int ret; - - if (!__JS_AtomIsTaggedInt(prop)) { - /* slow path with to handle all numeric indexes */ - num = JS_AtomIsNumericIndex1(ctx, prop); - if (JS_IsUndefined(num)) - goto typed_array_done; - if (JS_IsException(num)) - return -1; - ret = JS_NumberIsInteger(ctx, num); - if (ret < 0) { - JS_FreeValue(ctx, num); - return -1; - } - if (!ret) { - JS_FreeValue(ctx, num); - return JS_ThrowTypeErrorOrFalse(ctx, flags, "non integer index in typed array"); - } - ret = JS_NumberIsNegativeOrMinusZero(ctx, num); - JS_FreeValue(ctx, num); - if (ret) { - return JS_ThrowTypeErrorOrFalse(ctx, flags, "negative index in typed array"); - } - if (!__JS_AtomIsTaggedInt(prop)) - goto typed_array_oob; - } - idx = __JS_AtomToUInt32(prop); - /* if the typed array is detached, p->u.array.count = 0 */ - if (idx >= p->u.array.count) { - typed_array_oob: - return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound index in typed array"); - } - prop_flags = get_prop_flags(flags, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET) || - prop_flags != (JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE)) { - return JS_ThrowTypeErrorOrFalse(ctx, flags, "invalid descriptor flags"); - } - if (flags & JS_PROP_HAS_VALUE) { - return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), JS_DupValue(ctx, val), flags); - } - return TRUE; - typed_array_done: ; - } + } } return JS_CreateProperty(ctx, p, prop, val, getter, setter, flags); @@ -12732,60 +12378,6 @@ static void js_print_object(JSPrintValueState *s, JSObject *p) js_printf(s, "<%u empty item%s>", n, n > 1 ? "s" : ""); } } - } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && p->class_id <= JS_CLASS_FLOAT64_ARRAY) { - uint32_t size = 1 << typed_array_size_log2(p->class_id); - uint32_t len1; - int64_t v; - - js_print_atom(s, rt->class_array[p->class_id].class_name); - js_printf(s, "(%u) [ ", p->u.array.count); - - is_array = TRUE; - len1 = min_uint32(p->u.array.count, s->options.max_item_count); - for(i = 0; i < len1; i++) { - const uint8_t *ptr = p->u.array.u.uint8_ptr + i * size; - js_print_comma(s, &comma_state); - switch(p->class_id) { - case JS_CLASS_UINT8C_ARRAY: - case JS_CLASS_UINT8_ARRAY: - v = *ptr; - goto ta_int64; - case JS_CLASS_INT8_ARRAY: - v = *(int8_t *)ptr; - goto ta_int64; - case JS_CLASS_INT16_ARRAY: - v = *(int16_t *)ptr; - goto ta_int64; - case JS_CLASS_UINT16_ARRAY: - v = *(uint16_t *)ptr; - goto ta_int64; - case JS_CLASS_INT32_ARRAY: - v = *(int32_t *)ptr; - goto ta_int64; - case JS_CLASS_UINT32_ARRAY: - v = *(uint32_t *)ptr; - goto ta_int64; - case JS_CLASS_BIG_INT64_ARRAY: - v = *(int64_t *)ptr; - ta_int64: - js_printf(s, "%" PRId64, v); - break; - case JS_CLASS_BIG_UINT64_ARRAY: - js_printf(s, "%" PRIu64, *(uint64_t *)ptr); - break; - case JS_CLASS_FLOAT16_ARRAY: - js_print_float64(s, fromfp16(*(uint16_t *)ptr)); - break; - case JS_CLASS_FLOAT32_ARRAY: - js_print_float64(s, *(float *)ptr); - break; - case JS_CLASS_FLOAT64_ARRAY: - js_print_float64(s, *(double *)ptr); - break; - } - } - if (len1 < p->u.array.count) - js_print_more_items(s, &comma_state, p->u.array.count - len1); } else if (p->class_id == JS_CLASS_BYTECODE_FUNCTION || (rt->class_array[p->class_id].call != NULL && p->class_id != JS_CLASS_PROXY)) { @@ -30027,9 +29619,6 @@ typedef enum BCTagEnum { BC_TAG_TEMPLATE_OBJECT, BC_TAG_FUNCTION_BYTECODE, BC_TAG_MODULE, - BC_TAG_TYPED_ARRAY, - BC_TAG_ARRAY_BUFFER, - BC_TAG_SHARED_ARRAY_BUFFER, BC_TAG_OBJECT_VALUE, BC_TAG_OBJECT_REFERENCE, } BCTagEnum; @@ -30071,9 +29660,6 @@ static const char * const bc_tag_str[] = { "template", "function", "module", - "TypedArray", - "ArrayBuffer", - "SharedArrayBuffer", "ObjectValue", "ObjectReference", }; @@ -30522,50 +30108,6 @@ static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj) return -1; } -static int JS_WriteTypedArray(BCWriterState *s, JSValueConst obj) -{ - JSObject *p = JS_VALUE_GET_OBJ(obj); - JSTypedArray *ta = p->u.typed_array; - - bc_put_u8(s, BC_TAG_TYPED_ARRAY); - bc_put_u8(s, p->class_id - JS_CLASS_UINT8C_ARRAY); - bc_put_leb128(s, p->u.array.count); - bc_put_leb128(s, ta->offset); - if (JS_WriteObjectRec(s, JS_MKPTR(JS_TAG_OBJECT, ta->buffer))) - return -1; - return 0; -} - -static int JS_WriteArrayBuffer(BCWriterState *s, JSValueConst obj) -{ - JSObject *p = JS_VALUE_GET_OBJ(obj); - JSArrayBuffer *abuf = p->u.array_buffer; - if (abuf->detached) { - JS_ThrowTypeErrorDetachedArrayBuffer(s->ctx); - return -1; - } - bc_put_u8(s, BC_TAG_ARRAY_BUFFER); - bc_put_leb128(s, abuf->byte_length); - dbuf_put(&s->dbuf, abuf->data, abuf->byte_length); - return 0; -} - -static int JS_WriteSharedArrayBuffer(BCWriterState *s, JSValueConst obj) -{ - JSObject *p = JS_VALUE_GET_OBJ(obj); - JSArrayBuffer *abuf = p->u.array_buffer; - assert(!abuf->detached); /* SharedArrayBuffer are never detached */ - bc_put_u8(s, BC_TAG_SHARED_ARRAY_BUFFER); - bc_put_leb128(s, abuf->byte_length); - bc_put_u64(s, (uintptr_t)abuf->data); - if (js_resize_array(s->ctx, (void **)&s->sab_tab, sizeof(s->sab_tab[0]), - &s->sab_tab_size, s->sab_tab_len + 1)) - return -1; - /* keep the SAB pointer so that the user can clone it or free it */ - s->sab_tab[s->sab_tab_len++] = abuf->data; - return 0; -} - static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) { uint32_t tag; @@ -30650,14 +30192,6 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) case JS_CLASS_OBJECT: ret = JS_WriteObjectTag(s, obj); break; - case JS_CLASS_ARRAY_BUFFER: - ret = JS_WriteArrayBuffer(s, obj); - break; - case JS_CLASS_SHARED_ARRAY_BUFFER: - if (!s->allow_sab) - goto invalid_tag; - ret = JS_WriteSharedArrayBuffer(s, obj); - break; case JS_CLASS_NUMBER: case JS_CLASS_STRING: case JS_CLASS_BOOLEAN: @@ -30666,13 +30200,8 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) ret = JS_WriteObjectRec(s, p->u.object_data); break; default: - if (p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_FLOAT64_ARRAY) { - ret = JS_WriteTypedArray(s, obj); - } else { - JS_ThrowTypeError(s->ctx, "unsupported object class"); - ret = -1; - } + JS_ThrowTypeError(s->ctx, "unsupported object class"); + ret = -1; break; } p->tmp_mark = 0; @@ -31441,105 +30970,6 @@ static JSValue JS_ReadArray(BCReaderState *s, int tag) return JS_EXCEPTION; } -static JSValue JS_ReadTypedArray(BCReaderState *s) -{ - JSContext *ctx = s->ctx; - JSValue obj = JS_UNDEFINED, array_buffer = JS_UNDEFINED; - uint8_t array_tag; - JSValueConst args[3]; - uint32_t offset, len, idx; - - if (bc_get_u8(s, &array_tag)) - return JS_EXCEPTION; - if (array_tag >= JS_TYPED_ARRAY_COUNT) - return JS_ThrowTypeError(ctx, "invalid typed array"); - if (bc_get_leb128(s, &len)) - return JS_EXCEPTION; - if (bc_get_leb128(s, &offset)) - return JS_EXCEPTION; - /* XXX: this hack could be avoided if the typed array could be - created before the array buffer */ - idx = s->objects_count; - if (BC_add_object_ref1(s, NULL)) - goto fail; - array_buffer = JS_ReadObjectRec(s); - if (JS_IsException(array_buffer)) - return JS_EXCEPTION; - if (!js_get_array_buffer(ctx, array_buffer)) { - JS_FreeValue(ctx, array_buffer); - return JS_EXCEPTION; - } - args[0] = array_buffer; - args[1] = JS_NewInt64(ctx, offset); - args[2] = JS_NewInt64(ctx, len); - obj = js_typed_array_constructor(ctx, JS_UNDEFINED, - 3, args, - JS_CLASS_UINT8C_ARRAY + array_tag); - if (JS_IsException(obj)) - goto fail; - if (s->allow_reference) { - s->objects[idx] = JS_VALUE_GET_OBJ(obj); - } - JS_FreeValue(ctx, array_buffer); - return obj; - fail: - JS_FreeValue(ctx, array_buffer); - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; -} - -static JSValue JS_ReadArrayBuffer(BCReaderState *s) -{ - JSContext *ctx = s->ctx; - uint32_t byte_length; - JSValue obj; - - if (bc_get_leb128(s, &byte_length)) - return JS_EXCEPTION; - if (unlikely(s->buf_end - s->ptr < byte_length)) { - bc_read_error_end(s); - return JS_EXCEPTION; - } - obj = JS_NewArrayBufferCopy(ctx, s->ptr, byte_length); - if (JS_IsException(obj)) - goto fail; - if (BC_add_object_ref(s, obj)) - goto fail; - s->ptr += byte_length; - return obj; - fail: - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; -} - -static JSValue JS_ReadSharedArrayBuffer(BCReaderState *s) -{ - JSContext *ctx = s->ctx; - uint32_t byte_length; - uint8_t *data_ptr; - JSValue obj; - uint64_t u64; - - if (bc_get_leb128(s, &byte_length)) - return JS_EXCEPTION; - if (bc_get_u64(s, &u64)) - return JS_EXCEPTION; - data_ptr = (uint8_t *)(uintptr_t)u64; - /* the SharedArrayBuffer is cloned */ - obj = js_array_buffer_constructor3(ctx, JS_UNDEFINED, byte_length, - JS_CLASS_SHARED_ARRAY_BUFFER, - data_ptr, - NULL, NULL, FALSE); - if (JS_IsException(obj)) - goto fail; - if (BC_add_object_ref(s, obj)) - goto fail; - return obj; - fail: - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; -} - static JSValue JS_ReadObjectValue(BCReaderState *s) { JSContext *ctx = s->ctx; @@ -31625,17 +31055,6 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) case BC_TAG_TEMPLATE_OBJECT: obj = JS_ReadArray(s, tag); break; - case BC_TAG_TYPED_ARRAY: - obj = JS_ReadTypedArray(s); - break; - case BC_TAG_ARRAY_BUFFER: - obj = JS_ReadArrayBuffer(s); - break; - case BC_TAG_SHARED_ARRAY_BUFFER: - if (!s->allow_sab || !ctx->rt->sab_funcs.sab_dup) - goto invalid_tag; - obj = JS_ReadSharedArrayBuffer(s); - break; case BC_TAG_OBJECT_VALUE: obj = JS_ReadObjectValue(s); break; @@ -34269,13 +33688,6 @@ exception: #define special_forEach 2 #define special_map 3 #define special_filter 4 -#define special_TA 8 - -static int js_typed_array_get_length_internal(JSContext *ctx, JSValueConst obj); - -static JSValue js_typed_array___speciesCreate(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv); static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int special) @@ -34288,16 +33700,9 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, ret = JS_UNDEFINED; val = JS_UNDEFINED; - if (special & special_TA) { - obj = JS_DupValue(ctx, this_val); - len = js_typed_array_get_length_internal(ctx, obj); - if (len < 0) - goto exception; - } else { - obj = JS_ToObject(ctx, this_val); - if (js_get_length64(ctx, &len, obj)) - goto exception; - } + obj = JS_ToObject(ctx, this_val); + if (js_get_length64(ctx, &len, obj)) + goto exception; func = argv[0]; this_arg = JS_UNDEFINED; if (argc > 1) @@ -34308,11 +33713,9 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, switch (special) { case special_every: - case special_every | special_TA: ret = JS_TRUE; break; case special_some: - case special_some | special_TA: ret = JS_FALSE; break; case special_map: @@ -34326,32 +33729,13 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, if (JS_IsException(ret)) goto exception; break; - case special_map | special_TA: - args[0] = obj; - args[1] = JS_NewInt32(ctx, len); - ret = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args); - if (JS_IsException(ret)) - goto exception; - break; - case special_filter | special_TA: - ret = JS_NewArray(ctx); - if (JS_IsException(ret)) - goto exception; - break; } n = 0; for(k = 0; k < len; k++) { - if (special & special_TA) { - val = JS_GetPropertyInt64(ctx, obj, k); - if (JS_IsException(val)) - goto exception; - present = TRUE; - } else { - present = JS_TryGetPropertyInt64(ctx, obj, k, &val); - if (present < 0) - goto exception; - } + present = JS_TryGetPropertyInt64(ctx, obj, k, &val); + if (present < 0) + goto exception; if (present) { index_val = JS_NewInt64(ctx, k); if (JS_IsException(index_val)) @@ -34365,14 +33749,12 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, goto exception; switch (special) { case special_every: - case special_every | special_TA: if (!JS_ToBoolFree(ctx, res)) { ret = JS_FALSE; goto done; } break; case special_some: - case special_some | special_TA: if (JS_ToBoolFree(ctx, res)) { ret = JS_TRUE; goto done; @@ -34383,12 +33765,7 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, JS_PROP_C_W_E | JS_PROP_THROW) < 0) goto exception; break; - case special_map | special_TA: - if (JS_SetPropertyValue(ctx, ret, JS_NewInt32(ctx, k), res, JS_PROP_THROW) < 0) - goto exception; - break; case special_filter: - case special_filter | special_TA: if (JS_ToBoolFree(ctx, res)) { if (JS_DefinePropertyValueInt64(ctx, ret, n++, JS_DupValue(ctx, val), JS_PROP_C_W_E | JS_PROP_THROW) < 0) @@ -34404,20 +33781,6 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, } } done: - if (special == (special_filter | special_TA)) { - JSValue arr; - args[0] = obj; - args[1] = JS_NewInt32(ctx, n); - arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args); - if (JS_IsException(arr)) - goto exception; - args[0] = ret; - res = JS_Invoke(ctx, arr, JS_ATOM_set, 1, args); - if (check_exception_free(ctx, res)) - goto exception; - JS_FreeValue(ctx, ret); - ret = arr; - } JS_FreeValue(ctx, val); JS_FreeValue(ctx, obj); return ret; @@ -34443,16 +33806,9 @@ static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val, acc = JS_UNDEFINED; val = JS_UNDEFINED; - if (special & special_TA) { - obj = JS_DupValue(ctx, this_val); - len = js_typed_array_get_length_internal(ctx, obj); - if (len < 0) - goto exception; - } else { - obj = JS_ToObject(ctx, this_val); - if (js_get_length64(ctx, &len, obj)) - goto exception; - } + obj = JS_ToObject(ctx, this_val); + if (js_get_length64(ctx, &len, obj)) + goto exception; func = argv[0]; if (check_function(ctx, func)) @@ -34469,32 +33825,19 @@ static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val, } k1 = (special & special_reduceRight) ? len - k - 1 : k; k++; - if (special & special_TA) { - acc = JS_GetPropertyInt64(ctx, obj, k1); - if (JS_IsException(acc)) - goto exception; + present = JS_TryGetPropertyInt64(ctx, obj, k1, &acc); + if (present < 0) + goto exception; + if (present) break; - } else { - present = JS_TryGetPropertyInt64(ctx, obj, k1, &acc); - if (present < 0) - goto exception; - if (present) - break; - } } } for (; k < len; k++) { k1 = (special & special_reduceRight) ? len - k - 1 : k; - if (special & special_TA) { - val = JS_GetPropertyInt64(ctx, obj, k1); - if (JS_IsException(val)) - goto exception; - present = TRUE; - } else { - present = JS_TryGetPropertyInt64(ctx, obj, k1, &val); - if (present < 0) - goto exception; - } + present = JS_TryGetPropertyInt64(ctx, obj, k1, &val); + if (present < 0) + goto exception; + if (present) { index_val = JS_NewInt64(ctx, k1); if (JS_IsException(index_val)) @@ -35724,20 +35067,13 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, if (JS_IsUndefined(it->obj)) goto done; p = JS_VALUE_GET_OBJ(it->obj); - if (p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_FLOAT64_ARRAY) { - if (typed_array_is_detached(ctx, p)) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - goto fail1; - } - len = p->u.array.count; - } else { - if (js_get_length32(ctx, &len, it->obj)) { - fail1: - *pdone = FALSE; - return JS_EXCEPTION; - } + + if (js_get_length32(ctx, &len, it->obj)) { + fail1: + *pdone = FALSE; + return JS_EXCEPTION; } + idx = it->idx; if (idx >= len) { JS_FreeValue(ctx, it->obj); @@ -43589,3095 +42925,6 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) JS_AddIntrinsicBigInt(ctx); } -/* Typed Arrays */ - -static uint8_t const typed_array_size_log2[JS_TYPED_ARRAY_COUNT] = { - 0, 0, 0, 1, 1, 2, 2, - 3, 3, // BigInt64Array, BigUint64Array - 1, 2, 3 // Float16Array, Float32Array, Float64Array -}; - -static JSValue js_array_buffer_constructor3(JSContext *ctx, - JSValueConst new_target, - uint64_t len, JSClassID class_id, - uint8_t *buf, - JSFreeArrayBufferDataFunc *free_func, - void *opaque, BOOL alloc_flag) -{ - JSRuntime *rt = ctx->rt; - JSValue obj; - JSArrayBuffer *abuf = NULL; - - obj = js_create_from_ctor(ctx, new_target, class_id); - if (JS_IsException(obj)) - return obj; - /* XXX: we are currently limited to 2 GB */ - if (len > INT32_MAX) { - JS_ThrowRangeError(ctx, "invalid array buffer length"); - goto fail; - } - abuf = js_malloc(ctx, sizeof(*abuf)); - if (!abuf) - goto fail; - abuf->byte_length = len; - if (alloc_flag) { - if (class_id == JS_CLASS_SHARED_ARRAY_BUFFER && - rt->sab_funcs.sab_alloc) { - abuf->data = rt->sab_funcs.sab_alloc(rt->sab_funcs.sab_opaque, - max_int(len, 1)); - if (!abuf->data) - goto fail; - memset(abuf->data, 0, len); - } else { - /* the allocation must be done after the object creation */ - abuf->data = js_mallocz(ctx, max_int(len, 1)); - if (!abuf->data) - goto fail; - } - } else { - if (class_id == JS_CLASS_SHARED_ARRAY_BUFFER && - rt->sab_funcs.sab_dup) { - rt->sab_funcs.sab_dup(rt->sab_funcs.sab_opaque, buf); - } - abuf->data = buf; - } - init_list_head(&abuf->array_list); - abuf->detached = FALSE; - abuf->shared = (class_id == JS_CLASS_SHARED_ARRAY_BUFFER); - abuf->opaque = opaque; - abuf->free_func = free_func; - if (alloc_flag && buf) - memcpy(abuf->data, buf, len); - JS_SetOpaque(obj, abuf); - return obj; - fail: - JS_FreeValue(ctx, obj); - js_free(ctx, abuf); - return JS_EXCEPTION; -} - -static void js_array_buffer_free(JSRuntime *rt, void *opaque, void *ptr) -{ - js_free_rt(rt, ptr); -} - -static JSValue js_array_buffer_constructor2(JSContext *ctx, - JSValueConst new_target, - uint64_t len, JSClassID class_id) -{ - return js_array_buffer_constructor3(ctx, new_target, len, class_id, - NULL, js_array_buffer_free, NULL, - TRUE); -} - -static JSValue js_array_buffer_constructor1(JSContext *ctx, - JSValueConst new_target, - uint64_t len) -{ - return js_array_buffer_constructor2(ctx, new_target, len, - JS_CLASS_ARRAY_BUFFER); -} - -JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, - JSFreeArrayBufferDataFunc *free_func, void *opaque, - BOOL is_shared) -{ - return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, - is_shared ? JS_CLASS_SHARED_ARRAY_BUFFER : JS_CLASS_ARRAY_BUFFER, - buf, free_func, opaque, FALSE); -} - -/* create a new ArrayBuffer of length 'len' and copy 'buf' to it */ -JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len) -{ - return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, - JS_CLASS_ARRAY_BUFFER, - (uint8_t *)buf, - js_array_buffer_free, NULL, - TRUE); -} - -static JSValue js_array_buffer_constructor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv) -{ - uint64_t len; - if (JS_ToIndex(ctx, &len, argv[0])) - return JS_EXCEPTION; - return js_array_buffer_constructor1(ctx, new_target, len); -} - -static JSValue js_shared_array_buffer_constructor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv) -{ - uint64_t len; - if (JS_ToIndex(ctx, &len, argv[0])) - return JS_EXCEPTION; - return js_array_buffer_constructor2(ctx, new_target, len, - JS_CLASS_SHARED_ARRAY_BUFFER); -} - -/* also used for SharedArrayBuffer */ -static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val) -{ - JSObject *p = JS_VALUE_GET_OBJ(val); - JSArrayBuffer *abuf = p->u.array_buffer; - struct list_head *el, *el1; - - if (abuf) { - /* The ArrayBuffer finalizer may be called before the typed - array finalizers using it, so abuf->array_list is not - necessarily empty. */ - list_for_each_safe(el, el1, &abuf->array_list) { - JSTypedArray *ta; - JSObject *p1; - - ta = list_entry(el, JSTypedArray, link); - ta->link.prev = NULL; - ta->link.next = NULL; - p1 = ta->obj; - /* Note: the typed array length and offset fields are not modified */ - if (p1->class_id != JS_CLASS_DATAVIEW) { - p1->u.array.count = 0; - p1->u.array.u.ptr = NULL; - } - } - if (abuf->shared && rt->sab_funcs.sab_free) { - rt->sab_funcs.sab_free(rt->sab_funcs.sab_opaque, abuf->data); - } else { - if (abuf->free_func) - abuf->free_func(rt, abuf->opaque, abuf->data); - } - js_free_rt(rt, abuf); - } -} - -static JSValue js_array_buffer_isView(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSObject *p; - BOOL res; - res = FALSE; - if (JS_VALUE_GET_TAG(argv[0]) == JS_TAG_OBJECT) { - p = JS_VALUE_GET_OBJ(argv[0]); - if (p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_DATAVIEW) { - res = TRUE; - } - } - return JS_NewBool(ctx, res); -} - -static const JSCFunctionListEntry js_array_buffer_funcs[] = { - JS_CFUNC_DEF("isView", 1, js_array_buffer_isView ), - JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ), -}; - -static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx) -{ - return JS_ThrowTypeError(ctx, "ArrayBuffer is detached"); -} - -static JSValue js_array_buffer_get_byteLength(JSContext *ctx, - JSValueConst this_val, - int class_id) -{ - JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, class_id); - if (!abuf) - return JS_EXCEPTION; - /* return 0 if detached */ - return JS_NewUint32(ctx, abuf->byte_length); -} - -void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj) -{ - JSArrayBuffer *abuf = JS_GetOpaque(obj, JS_CLASS_ARRAY_BUFFER); - struct list_head *el; - - if (!abuf || abuf->detached) - return; - if (abuf->free_func) - abuf->free_func(ctx->rt, abuf->opaque, abuf->data); - abuf->data = NULL; - abuf->byte_length = 0; - abuf->detached = TRUE; - - list_for_each(el, &abuf->array_list) { - JSTypedArray *ta; - JSObject *p; - - ta = list_entry(el, JSTypedArray, link); - p = ta->obj; - /* Note: the typed array length and offset fields are not modified */ - if (p->class_id != JS_CLASS_DATAVIEW) { - p->u.array.count = 0; - p->u.array.u.ptr = NULL; - } - } -} - -/* get an ArrayBuffer or SharedArrayBuffer */ -static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj) -{ - JSObject *p; - if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) - goto fail; - p = JS_VALUE_GET_OBJ(obj); - if (p->class_id != JS_CLASS_ARRAY_BUFFER && - p->class_id != JS_CLASS_SHARED_ARRAY_BUFFER) { - fail: - JS_ThrowTypeErrorInvalidClass(ctx, JS_CLASS_ARRAY_BUFFER); - return NULL; - } - return p->u.array_buffer; -} - -/* return NULL if exception. WARNING: any JS call can detach the - buffer and render the returned pointer invalid */ -uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj) -{ - JSArrayBuffer *abuf = js_get_array_buffer(ctx, obj); - if (!abuf) - goto fail; - if (abuf->detached) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - goto fail; - } - *psize = abuf->byte_length; - return abuf->data; - fail: - *psize = 0; - return NULL; -} - -static JSValue js_array_buffer_slice(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv, int class_id) -{ - JSArrayBuffer *abuf, *new_abuf; - int64_t len, start, end, new_len; - JSValue ctor, new_obj; - - abuf = JS_GetOpaque2(ctx, this_val, class_id); - if (!abuf) - return JS_EXCEPTION; - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - len = abuf->byte_length; - - if (JS_ToInt64Clamp(ctx, &start, argv[0], 0, len, len)) - return JS_EXCEPTION; - - end = len; - if (!JS_IsUndefined(argv[1])) { - if (JS_ToInt64Clamp(ctx, &end, argv[1], 0, len, len)) - return JS_EXCEPTION; - } - new_len = max_int64(end - start, 0); - ctor = JS_SpeciesConstructor(ctx, this_val, JS_UNDEFINED); - if (JS_IsException(ctor)) - return ctor; - if (JS_IsUndefined(ctor)) { - new_obj = js_array_buffer_constructor2(ctx, JS_UNDEFINED, new_len, - class_id); - } else { - JSValue args[1]; - args[0] = JS_NewInt64(ctx, new_len); - new_obj = JS_CallConstructor(ctx, ctor, 1, (JSValueConst *)args); - JS_FreeValue(ctx, ctor); - JS_FreeValue(ctx, args[0]); - } - if (JS_IsException(new_obj)) - return new_obj; - new_abuf = JS_GetOpaque2(ctx, new_obj, class_id); - if (!new_abuf) - goto fail; - if (js_same_value(ctx, new_obj, this_val)) { - JS_ThrowTypeError(ctx, "cannot use identical ArrayBuffer"); - goto fail; - } - if (new_abuf->detached) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - goto fail; - } - if (new_abuf->byte_length < new_len) { - JS_ThrowTypeError(ctx, "new ArrayBuffer is too small"); - goto fail; - } - /* must test again because of side effects */ - if (abuf->detached) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - goto fail; - } - memcpy(new_abuf->data, abuf->data + start, new_len); - return new_obj; - fail: - JS_FreeValue(ctx, new_obj); - return JS_EXCEPTION; -} - -static const JSCFunctionListEntry js_array_buffer_proto_funcs[] = { - JS_CGETSET_MAGIC_DEF("byteLength", js_array_buffer_get_byteLength, NULL, JS_CLASS_ARRAY_BUFFER ), - JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_ARRAY_BUFFER ), - JS_PROP_STRING_DEF("[Symbol.toStringTag]", "ArrayBuffer", JS_PROP_CONFIGURABLE ), -}; - -/* SharedArrayBuffer */ - -static const JSCFunctionListEntry js_shared_array_buffer_funcs[] = { - JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ), -}; - -static const JSCFunctionListEntry js_shared_array_buffer_proto_funcs[] = { - JS_CGETSET_MAGIC_DEF("byteLength", js_array_buffer_get_byteLength, NULL, JS_CLASS_SHARED_ARRAY_BUFFER ), - JS_CFUNC_MAGIC_DEF("slice", 2, js_array_buffer_slice, JS_CLASS_SHARED_ARRAY_BUFFER ), - JS_PROP_STRING_DEF("[Symbol.toStringTag]", "SharedArrayBuffer", JS_PROP_CONFIGURABLE ), -}; - -static JSObject *get_typed_array(JSContext *ctx, - JSValueConst this_val, - int is_dataview) -{ - JSObject *p; - if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT) - goto fail; - p = JS_VALUE_GET_OBJ(this_val); - if (is_dataview) { - if (p->class_id != JS_CLASS_DATAVIEW) - goto fail; - } else { - if (!(p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_FLOAT64_ARRAY)) { - fail: - JS_ThrowTypeError(ctx, "not a %s", is_dataview ? "DataView" : "TypedArray"); - return NULL; - } - } - return p; -} - -/* WARNING: 'p' must be a typed array */ -static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p) -{ - JSTypedArray *ta = p->u.typed_array; - JSArrayBuffer *abuf = ta->buffer->u.array_buffer; - /* XXX: could simplify test by ensuring that - p->u.array.u.ptr is NULL iff it is detached */ - return abuf->detached; -} - -/* WARNING: 'p' must be a typed array. Works even if the array buffer - is detached */ -static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p) -{ - JSTypedArray *ta = p->u.typed_array; - int size_log2 = typed_array_size_log2(p->class_id); - return ta->length >> size_log2; -} - -static int validate_typed_array(JSContext *ctx, JSValueConst this_val) -{ - JSObject *p; - p = get_typed_array(ctx, this_val, 0); - if (!p) - return -1; - if (typed_array_is_detached(ctx, p)) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - return -1; - } - return 0; -} - -static JSValue js_typed_array_get_length(JSContext *ctx, - JSValueConst this_val) -{ - JSObject *p; - p = get_typed_array(ctx, this_val, 0); - if (!p) - return JS_EXCEPTION; - return JS_NewInt32(ctx, p->u.array.count); -} - -static JSValue js_typed_array_get_buffer(JSContext *ctx, - JSValueConst this_val, int is_dataview) -{ - JSObject *p; - JSTypedArray *ta; - p = get_typed_array(ctx, this_val, is_dataview); - if (!p) - return JS_EXCEPTION; - ta = p->u.typed_array; - return JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); -} - -static JSValue js_typed_array_get_byteLength(JSContext *ctx, - JSValueConst this_val, - int is_dataview) -{ - JSObject *p; - JSTypedArray *ta; - p = get_typed_array(ctx, this_val, is_dataview); - if (!p) - return JS_EXCEPTION; - if (typed_array_is_detached(ctx, p)) { - if (is_dataview) { - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - } else { - return JS_NewInt32(ctx, 0); - } - } - ta = p->u.typed_array; - return JS_NewInt32(ctx, ta->length); -} - -static JSValue js_typed_array_get_byteOffset(JSContext *ctx, - JSValueConst this_val, - int is_dataview) -{ - JSObject *p; - JSTypedArray *ta; - p = get_typed_array(ctx, this_val, is_dataview); - if (!p) - return JS_EXCEPTION; - if (typed_array_is_detached(ctx, p)) { - if (is_dataview) { - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - } else { - return JS_NewInt32(ctx, 0); - } - } - ta = p->u.typed_array; - return JS_NewInt32(ctx, ta->offset); -} - -JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv, - JSTypedArrayEnum type) -{ - if (type < JS_TYPED_ARRAY_UINT8C || type > JS_TYPED_ARRAY_FLOAT64) - return JS_ThrowRangeError(ctx, "invalid typed array type"); - - return js_typed_array_constructor(ctx, JS_UNDEFINED, argc, argv, - JS_CLASS_UINT8C_ARRAY + type); -} - -/* Return the buffer associated to the typed array or an exception if - it is not a typed array or if the buffer is detached. pbyte_offset, - pbyte_length or pbytes_per_element can be NULL. */ -JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, - size_t *pbyte_offset, - size_t *pbyte_length, - size_t *pbytes_per_element) -{ - JSObject *p; - JSTypedArray *ta; - p = get_typed_array(ctx, obj, FALSE); - if (!p) - return JS_EXCEPTION; - if (typed_array_is_detached(ctx, p)) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - ta = p->u.typed_array; - if (pbyte_offset) - *pbyte_offset = ta->offset; - if (pbyte_length) - *pbyte_length = ta->length; - if (pbytes_per_element) { - *pbytes_per_element = 1 << typed_array_size_log2(p->class_id); - } - return JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); -} - -static JSValue js_typed_array_get_toStringTag(JSContext *ctx, - JSValueConst this_val) -{ - JSObject *p; - if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT) - return JS_UNDEFINED; - p = JS_VALUE_GET_OBJ(this_val); - if (!(p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_FLOAT64_ARRAY)) - return JS_UNDEFINED; - return JS_AtomToString(ctx, ctx->rt->class_array[p->class_id].class_name); -} - -static JSValue js_typed_array_set_internal(JSContext *ctx, - JSValueConst dst, - JSValueConst src, - JSValueConst off) -{ - JSObject *p; - JSObject *src_p; - uint32_t i; - int64_t src_len, offset; - JSValue val, src_obj = JS_UNDEFINED; - - p = get_typed_array(ctx, dst, 0); - if (!p) - goto fail; - if (JS_ToInt64Sat(ctx, &offset, off)) - goto fail; - if (offset < 0) - goto range_error; - if (typed_array_is_detached(ctx, p)) { - detached: - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - goto fail; - } - src_obj = JS_ToObject(ctx, src); - if (JS_IsException(src_obj)) - goto fail; - src_p = JS_VALUE_GET_OBJ(src_obj); - if (src_p->class_id >= JS_CLASS_UINT8C_ARRAY && - src_p->class_id <= JS_CLASS_FLOAT64_ARRAY) { - JSTypedArray *dest_ta = p->u.typed_array; - JSArrayBuffer *dest_abuf = dest_ta->buffer->u.array_buffer; - JSTypedArray *src_ta = src_p->u.typed_array; - JSArrayBuffer *src_abuf = src_ta->buffer->u.array_buffer; - int shift = typed_array_size_log2(p->class_id); - - if (src_abuf->detached) - goto detached; - - src_len = src_p->u.array.count; - if (offset > (int64_t)(p->u.array.count - src_len)) - goto range_error; - - /* copying between typed objects */ - if (src_p->class_id == p->class_id) { - /* same type, use memmove */ - memmove(dest_abuf->data + dest_ta->offset + (offset << shift), - src_abuf->data + src_ta->offset, src_len << shift); - goto done; - } - if (dest_abuf->data == src_abuf->data) { - /* copying between the same buffer using different types of mappings - would require a temporary buffer */ - } - /* otherwise, default behavior is slow but correct */ - } else { - if (js_get_length64(ctx, &src_len, src_obj)) - goto fail; - if (offset > (int64_t)(p->u.array.count - src_len)) { - range_error: - JS_ThrowRangeError(ctx, "invalid array length"); - goto fail; - } - } - for(i = 0; i < src_len; i++) { - val = JS_GetPropertyUint32(ctx, src_obj, i); - if (JS_IsException(val)) - goto fail; - if (JS_SetPropertyUint32(ctx, dst, offset + i, val) < 0) - goto fail; - } -done: - JS_FreeValue(ctx, src_obj); - return JS_UNDEFINED; -fail: - JS_FreeValue(ctx, src_obj); - return JS_EXCEPTION; -} - -static JSValue js_typed_array_at(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSObject *p; - int64_t idx, len; - - p = get_typed_array(ctx, this_val, 0); - if (!p) - return JS_EXCEPTION; - - if (typed_array_is_detached(ctx, p)) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - return JS_EXCEPTION; - } - - if (JS_ToInt64Sat(ctx, &idx, argv[0])) - return JS_EXCEPTION; - - len = p->u.array.count; - if (idx < 0) - idx = len + idx; - if (idx < 0 || idx >= len) - return JS_UNDEFINED; - return JS_GetPropertyInt64(ctx, this_val, idx); -} - -static JSValue js_typed_array_with(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue arr, val; - JSObject *p; - int64_t idx, len; - - p = get_typed_array(ctx, this_val, /*is_dataview*/0); - if (!p) - return JS_EXCEPTION; - if (typed_array_is_detached(ctx, p)) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - - if (JS_ToInt64Sat(ctx, &idx, argv[0])) - return JS_EXCEPTION; - - len = p->u.array.count; - if (idx < 0) - idx = len + idx; - - val = JS_ToPrimitive(ctx, argv[1], HINT_NUMBER); - if (JS_IsException(val)) - return JS_EXCEPTION; - - if (typed_array_is_detached(ctx, p) || idx < 0 || idx >= len) - return JS_ThrowRangeError(ctx, "invalid array index"); - - arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val, - p->class_id); - if (JS_IsException(arr)) { - JS_FreeValue(ctx, val); - return JS_EXCEPTION; - } - if (JS_SetPropertyInt64(ctx, arr, idx, val) < 0) { - JS_FreeValue(ctx, arr); - return JS_EXCEPTION; - } - return arr; -} - -static JSValue js_typed_array_set(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValueConst offset = JS_UNDEFINED; - if (argc > 1) { - offset = argv[1]; - } - return js_typed_array_set_internal(ctx, this_val, argv[0], offset); -} - -static JSValue js_create_typed_array_iterator(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int magic) -{ - if (validate_typed_array(ctx, this_val)) - return JS_EXCEPTION; - return js_create_array_iterator(ctx, this_val, argc, argv, magic); -} - -/* return < 0 if exception */ -static int js_typed_array_get_length_internal(JSContext *ctx, - JSValueConst obj) -{ - JSObject *p; - p = get_typed_array(ctx, obj, 0); - if (!p) - return -1; - if (typed_array_is_detached(ctx, p)) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - return -1; - } - return p->u.array.count; -} - -#if 0 -/* validate a typed array and return its length */ -static JSValue js_typed_array___getLength(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv) -{ - BOOL ignore_detached = JS_ToBool(ctx, argv[1]); - - if (ignore_detached) { - return js_typed_array_get_length(ctx, argv[0]); - } else { - int len; - len = js_typed_array_get_length_internal(ctx, argv[0]); - if (len < 0) - return JS_EXCEPTION; - return JS_NewInt32(ctx, len); - } -} -#endif - -static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor, - int argc, JSValueConst *argv) -{ - JSValue ret; - int new_len; - int64_t len; - - ret = JS_CallConstructor(ctx, ctor, argc, argv); - if (JS_IsException(ret)) - return ret; - /* validate the typed array */ - new_len = js_typed_array_get_length_internal(ctx, ret); - if (new_len < 0) - goto fail; - if (argc == 1) { - /* ensure that it is large enough */ - if (JS_ToLengthFree(ctx, &len, JS_DupValue(ctx, argv[0]))) - goto fail; - if (new_len < len) { - JS_ThrowTypeError(ctx, "TypedArray length is too small"); - fail: - JS_FreeValue(ctx, ret); - return JS_EXCEPTION; - } - } - return ret; -} - -#if 0 -static JSValue js_typed_array___create(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return js_typed_array_create(ctx, argv[0], max_int(argc - 1, 0), argv + 1); -} -#endif - -static JSValue js_typed_array___speciesCreate(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValueConst obj; - JSObject *p; - JSValue ctor, ret; - int argc1; - - obj = argv[0]; - p = get_typed_array(ctx, obj, 0); - if (!p) - return JS_EXCEPTION; - ctor = JS_SpeciesConstructor(ctx, obj, JS_UNDEFINED); - if (JS_IsException(ctor)) - return ctor; - argc1 = max_int(argc - 1, 0); - if (JS_IsUndefined(ctor)) { - ret = js_typed_array_constructor(ctx, JS_UNDEFINED, argc1, argv + 1, - p->class_id); - } else { - ret = js_typed_array_create(ctx, ctor, argc1, argv + 1); - JS_FreeValue(ctx, ctor); - } - return ret; -} - -static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - // from(items, mapfn = void 0, this_arg = void 0) - JSValueConst items = argv[0], mapfn, this_arg; - JSValueConst args[2]; - JSValue iter, arr, r, v, v2; - int64_t k, len; - int mapping; - - mapping = FALSE; - mapfn = JS_UNDEFINED; - this_arg = JS_UNDEFINED; - r = JS_UNDEFINED; - arr = JS_UNDEFINED; - iter = JS_UNDEFINED; - - if (argc > 1) { - mapfn = argv[1]; - if (!JS_IsUndefined(mapfn)) { - if (check_function(ctx, mapfn)) - goto exception; - mapping = 1; - if (argc > 2) - this_arg = argv[2]; - } - } - iter = JS_GetProperty(ctx, items, JS_ATOM_Symbol_iterator); - if (JS_IsException(iter)) - goto exception; - if (!JS_IsUndefined(iter) && !JS_IsNull(iter)) { - uint32_t len1; - if (!JS_IsFunction(ctx, iter)) { - JS_ThrowTypeError(ctx, "value is not iterable"); - goto exception; - } - arr = js_array_from_iterator(ctx, &len1, items, iter); - if (JS_IsException(arr)) - goto exception; - len = len1; - } else { - arr = JS_ToObject(ctx, items); - if (JS_IsException(arr)) - goto exception; - if (js_get_length64(ctx, &len, arr) < 0) - goto exception; - } - v = JS_NewInt64(ctx, len); - args[0] = v; - r = js_typed_array_create(ctx, this_val, 1, args); - JS_FreeValue(ctx, v); - if (JS_IsException(r)) - goto exception; - for(k = 0; k < len; k++) { - v = JS_GetPropertyInt64(ctx, arr, k); - if (JS_IsException(v)) - goto exception; - if (mapping) { - args[0] = v; - args[1] = JS_NewInt32(ctx, k); - v2 = JS_Call(ctx, mapfn, this_arg, 2, args); - JS_FreeValue(ctx, v); - v = v2; - if (JS_IsException(v)) - goto exception; - } - if (JS_SetPropertyInt64(ctx, r, k, v) < 0) - goto exception; - } - goto done; - exception: - JS_FreeValue(ctx, r); - r = JS_EXCEPTION; - done: - JS_FreeValue(ctx, arr); - JS_FreeValue(ctx, iter); - return r; -} - -static JSValue js_typed_array_of(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue obj; - JSValueConst args[1]; - int i; - - args[0] = JS_NewInt32(ctx, argc); - obj = js_typed_array_create(ctx, this_val, 1, args); - if (JS_IsException(obj)) - return obj; - - for(i = 0; i < argc; i++) { - if (JS_SetPropertyUint32(ctx, obj, i, JS_DupValue(ctx, argv[i])) < 0) { - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } - } - return obj; -} - -static JSValue js_typed_array_copyWithin(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSObject *p; - int len, to, from, final, count, shift; - - len = js_typed_array_get_length_internal(ctx, this_val); - if (len < 0) - return JS_EXCEPTION; - - if (JS_ToInt32Clamp(ctx, &to, argv[0], 0, len, len)) - return JS_EXCEPTION; - - if (JS_ToInt32Clamp(ctx, &from, argv[1], 0, len, len)) - return JS_EXCEPTION; - - final = len; - if (argc > 2 && !JS_IsUndefined(argv[2])) { - if (JS_ToInt32Clamp(ctx, &final, argv[2], 0, len, len)) - return JS_EXCEPTION; - } - - count = min_int(final - from, len - to); - if (count > 0) { - p = JS_VALUE_GET_OBJ(this_val); - if (typed_array_is_detached(ctx, p)) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - shift = typed_array_size_log2(p->class_id); - memmove(p->u.array.u.uint8_ptr + (to << shift), - p->u.array.u.uint8_ptr + (from << shift), - count << shift); - } - return JS_DupValue(ctx, this_val); -} - -static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSObject *p; - int len, k, final, shift; - uint64_t v64; - - len = js_typed_array_get_length_internal(ctx, this_val); - if (len < 0) - return JS_EXCEPTION; - p = JS_VALUE_GET_OBJ(this_val); - - if (p->class_id == JS_CLASS_UINT8C_ARRAY) { - int32_t v; - if (JS_ToUint8ClampFree(ctx, &v, JS_DupValue(ctx, argv[0]))) - return JS_EXCEPTION; - v64 = v; - } else if (p->class_id <= JS_CLASS_UINT32_ARRAY) { - uint32_t v; - if (JS_ToUint32(ctx, &v, argv[0])) - return JS_EXCEPTION; - v64 = v; - } else if (p->class_id <= JS_CLASS_BIG_UINT64_ARRAY) { - if (JS_ToBigInt64(ctx, (int64_t *)&v64, argv[0])) - return JS_EXCEPTION; - } else { - double d; - if (JS_ToFloat64(ctx, &d, argv[0])) - return JS_EXCEPTION; - if (p->class_id == JS_CLASS_FLOAT16_ARRAY) { - v64 = tofp16(d); - } else if (p->class_id == JS_CLASS_FLOAT32_ARRAY) { - union { - float f; - uint32_t u32; - } u; - u.f = d; - v64 = u.u32; - } else { - JSFloat64Union u; - u.d = d; - v64 = u.u64; - } - } - - k = 0; - if (argc > 1) { - if (JS_ToInt32Clamp(ctx, &k, argv[1], 0, len, len)) - return JS_EXCEPTION; - } - - final = len; - if (argc > 2 && !JS_IsUndefined(argv[2])) { - if (JS_ToInt32Clamp(ctx, &final, argv[2], 0, len, len)) - return JS_EXCEPTION; - } - - if (typed_array_is_detached(ctx, p)) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - - shift = typed_array_size_log2(p->class_id); - switch(shift) { - case 0: - if (k < final) { - memset(p->u.array.u.uint8_ptr + k, v64, final - k); - } - break; - case 1: - for(; k < final; k++) { - p->u.array.u.uint16_ptr[k] = v64; - } - break; - case 2: - for(; k < final; k++) { - p->u.array.u.uint32_ptr[k] = v64; - } - break; - case 3: - for(; k < final; k++) { - p->u.array.u.uint64_ptr[k] = v64; - } - break; - default: - abort(); - } - return JS_DupValue(ctx, this_val); -} - -static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int mode) -{ - JSValueConst func, this_arg; - JSValueConst args[3]; - JSValue val, index_val, res; - int len, k, end; - int dir; - - val = JS_UNDEFINED; - len = js_typed_array_get_length_internal(ctx, this_val); - if (len < 0) - goto exception; - - func = argv[0]; - if (check_function(ctx, func)) - goto exception; - - this_arg = JS_UNDEFINED; - if (argc > 1) - this_arg = argv[1]; - - k = 0; - dir = 1; - end = len; - if (mode == ArrayFindLast || mode == ArrayFindLastIndex) { - k = len - 1; - dir = -1; - end = -1; - } - - for(; k != end; k += dir) { - index_val = JS_NewInt32(ctx, k); - val = JS_GetPropertyValue(ctx, this_val, index_val); - if (JS_IsException(val)) - goto exception; - args[0] = val; - args[1] = index_val; - args[2] = this_val; - res = JS_Call(ctx, func, this_arg, 3, args); - if (JS_IsException(res)) - goto exception; - if (JS_ToBoolFree(ctx, res)) { - if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) { - JS_FreeValue(ctx, val); - return index_val; - } else { - return val; - } - } - JS_FreeValue(ctx, val); - } - if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) - return JS_NewInt32(ctx, -1); - else - return JS_UNDEFINED; - -exception: - JS_FreeValue(ctx, val); - return JS_EXCEPTION; -} - -#define special_indexOf 0 -#define special_lastIndexOf 1 -#define special_includes -1 - -static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int special) -{ - JSObject *p; - int len, tag, is_int, is_bigint, k, stop, inc, res = -1; - int64_t v64; - double d; - float f; - uint16_t hf; - - len = js_typed_array_get_length_internal(ctx, this_val); - if (len < 0) - goto exception; - if (len == 0) - goto done; - - if (special == special_lastIndexOf) { - k = len - 1; - if (argc > 1) { - if (JS_ToFloat64(ctx, &d, argv[1])) - goto exception; - if (isnan(d)) { - k = 0; - } else { - if (d >= 0) { - if (d < k) { - k = d; - } - } else { - d += len; - if (d < 0) - goto done; - k = d; - } - } - } - stop = -1; - inc = -1; - } else { - k = 0; - if (argc > 1) { - if (JS_ToInt32Clamp(ctx, &k, argv[1], 0, len, len)) - goto exception; - } - stop = len; - inc = 1; - } - - p = JS_VALUE_GET_OBJ(this_val); - /* if the array was detached, no need to go further (but no - exception is raised) */ - if (typed_array_is_detached(ctx, p)) { - /* "includes" scans all the properties, so "undefined" can match */ - if (special == special_includes && JS_IsUndefined(argv[0]) && len > 0) - res = 0; - goto done; - } - - is_bigint = 0; - is_int = 0; /* avoid warning */ - v64 = 0; /* avoid warning */ - tag = JS_VALUE_GET_NORM_TAG(argv[0]); - if (tag == JS_TAG_INT) { - is_int = 1; - v64 = JS_VALUE_GET_INT(argv[0]); - d = v64; - } else - if (tag == JS_TAG_FLOAT64) { - d = JS_VALUE_GET_FLOAT64(argv[0]); - if (d >= INT64_MIN && d < 0x1p63) { - v64 = d; - is_int = (v64 == d); - } - } else if (tag == JS_TAG_BIG_INT || tag == JS_TAG_SHORT_BIG_INT) { - JSBigIntBuf buf1; - JSBigInt *p1; - int sz = (64 / JS_LIMB_BITS); - if (tag == JS_TAG_SHORT_BIG_INT) - p1 = js_bigint_set_short(&buf1, argv[0]); - else - p1 = JS_VALUE_GET_PTR(argv[0]); - - if (p->class_id == JS_CLASS_BIG_INT64_ARRAY) { - if (p1->len > sz) - goto done; /* does not fit an int64 : cannot be found */ - } else if (p->class_id == JS_CLASS_BIG_UINT64_ARRAY) { - if (js_bigint_sign(p1)) - goto done; /* v < 0 */ - if (p1->len <= sz) { - /* OK */ - } else if (p1->len == sz + 1 && p1->tab[sz] == 0) { - /* 2^63 <= v <= 2^64-1 */ - } else { - goto done; - } - } else { - goto done; - } - if (JS_ToBigInt64(ctx, &v64, argv[0])) - goto exception; - d = 0; - is_bigint = 1; - } else { - goto done; - } - - switch (p->class_id) { - case JS_CLASS_INT8_ARRAY: - if (is_int && (int8_t)v64 == v64) - goto scan8; - break; - case JS_CLASS_UINT8C_ARRAY: - case JS_CLASS_UINT8_ARRAY: - if (is_int && (uint8_t)v64 == v64) { - const uint8_t *pv, *pp; - uint16_t v; - scan8: - pv = p->u.array.u.uint8_ptr; - v = v64; - if (inc > 0) { - pp = memchr(pv + k, v, len - k); - if (pp) - res = pp - pv; - } else { - for (; k != stop; k += inc) { - if (pv[k] == v) { - res = k; - break; - } - } - } - } - break; - case JS_CLASS_INT16_ARRAY: - if (is_int && (int16_t)v64 == v64) - goto scan16; - break; - case JS_CLASS_UINT16_ARRAY: - if (is_int && (uint16_t)v64 == v64) { - const uint16_t *pv; - uint16_t v; - scan16: - pv = p->u.array.u.uint16_ptr; - v = v64; - for (; k != stop; k += inc) { - if (pv[k] == v) { - res = k; - break; - } - } - } - break; - case JS_CLASS_INT32_ARRAY: - if (is_int && (int32_t)v64 == v64) - goto scan32; - break; - case JS_CLASS_UINT32_ARRAY: - if (is_int && (uint32_t)v64 == v64) { - const uint32_t *pv; - uint32_t v; - scan32: - pv = p->u.array.u.uint32_ptr; - v = v64; - for (; k != stop; k += inc) { - if (pv[k] == v) { - res = k; - break; - } - } - } - break; - case JS_CLASS_FLOAT16_ARRAY: - if (is_bigint) - break; - if (isnan(d)) { - const uint16_t *pv = p->u.array.u.fp16_ptr; - /* special case: indexOf returns -1, includes finds NaN */ - if (special != special_includes) - goto done; - for (; k != stop; k += inc) { - if (isfp16nan(pv[k])) { - res = k; - break; - } - } - } else if (d == 0) { - // special case: includes also finds negative zero - const uint16_t *pv = p->u.array.u.fp16_ptr; - for (; k != stop; k += inc) { - if (isfp16zero(pv[k])) { - res = k; - break; - } - } - } else if (hf = tofp16(d), d == fromfp16(hf)) { - const uint16_t *pv = p->u.array.u.fp16_ptr; - for (; k != stop; k += inc) { - if (pv[k] == hf) { - res = k; - break; - } - } - } - break; - case JS_CLASS_FLOAT32_ARRAY: - if (is_bigint) - break; - if (isnan(d)) { - const float *pv = p->u.array.u.float_ptr; - /* special case: indexOf returns -1, includes finds NaN */ - if (special != special_includes) - goto done; - for (; k != stop; k += inc) { - if (isnan(pv[k])) { - res = k; - break; - } - } - } else if ((f = (float)d) == d) { - const float *pv = p->u.array.u.float_ptr; - for (; k != stop; k += inc) { - if (pv[k] == f) { - res = k; - break; - } - } - } - break; - case JS_CLASS_FLOAT64_ARRAY: - if (is_bigint) - break; - if (isnan(d)) { - const double *pv = p->u.array.u.double_ptr; - /* special case: indexOf returns -1, includes finds NaN */ - if (special != special_includes) - goto done; - for (; k != stop; k += inc) { - if (isnan(pv[k])) { - res = k; - break; - } - } - } else { - const double *pv = p->u.array.u.double_ptr; - for (; k != stop; k += inc) { - if (pv[k] == d) { - res = k; - break; - } - } - } - break; - case JS_CLASS_BIG_INT64_ARRAY: - if (is_bigint) { - goto scan64; - } - break; - case JS_CLASS_BIG_UINT64_ARRAY: - if (is_bigint) { - const uint64_t *pv; - uint64_t v; - scan64: - pv = p->u.array.u.uint64_ptr; - v = v64; - for (; k != stop; k += inc) { - if (pv[k] == v) { - res = k; - break; - } - } - } - break; - } - -done: - if (special == special_includes) - return JS_NewBool(ctx, res >= 0); - else - return JS_NewInt32(ctx, res); - -exception: - return JS_EXCEPTION; -} - -static JSValue js_typed_array_join(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int toLocaleString) -{ - JSValue sep = JS_UNDEFINED, el; - StringBuffer b_s, *b = &b_s; - JSString *p = NULL; - int i, n; - int c; - - n = js_typed_array_get_length_internal(ctx, this_val); - if (n < 0) - goto exception; - - c = ','; /* default separator */ - if (!toLocaleString && argc > 0 && !JS_IsUndefined(argv[0])) { - sep = JS_ToString(ctx, argv[0]); - if (JS_IsException(sep)) - goto exception; - p = JS_VALUE_GET_STRING(sep); - if (p->len == 1 && !p->is_wide_char) - c = p->u.str8[0]; - else - c = -1; - } - string_buffer_init(ctx, b, 0); - - /* XXX: optimize with direct access */ - for(i = 0; i < n; i++) { - if (i > 0) { - if (c >= 0) { - if (string_buffer_putc8(b, c)) - goto fail; - } else { - if (string_buffer_concat(b, p, 0, p->len)) - goto fail; - } - } - el = JS_GetPropertyUint32(ctx, this_val, i); - /* Can return undefined for example if the typed array is detached */ - if (!JS_IsNull(el) && !JS_IsUndefined(el)) { - if (JS_IsException(el)) - goto fail; - if (toLocaleString) { - el = JS_ToLocaleStringFree(ctx, el); - } - if (string_buffer_concat_value_free(b, el)) - goto fail; - } - } - JS_FreeValue(ctx, sep); - return string_buffer_end(b); - -fail: - string_buffer_free(b); - JS_FreeValue(ctx, sep); -exception: - return JS_EXCEPTION; -} - -static JSValue js_typed_array_reverse(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSObject *p; - int len; - - len = js_typed_array_get_length_internal(ctx, this_val); - if (len < 0) - return JS_EXCEPTION; - if (len > 0) { - p = JS_VALUE_GET_OBJ(this_val); - switch (typed_array_size_log2(p->class_id)) { - case 0: - { - uint8_t *p1 = p->u.array.u.uint8_ptr; - uint8_t *p2 = p1 + len - 1; - while (p1 < p2) { - uint8_t v = *p1; - *p1++ = *p2; - *p2-- = v; - } - } - break; - case 1: - { - uint16_t *p1 = p->u.array.u.uint16_ptr; - uint16_t *p2 = p1 + len - 1; - while (p1 < p2) { - uint16_t v = *p1; - *p1++ = *p2; - *p2-- = v; - } - } - break; - case 2: - { - uint32_t *p1 = p->u.array.u.uint32_ptr; - uint32_t *p2 = p1 + len - 1; - while (p1 < p2) { - uint32_t v = *p1; - *p1++ = *p2; - *p2-- = v; - } - } - break; - case 3: - { - uint64_t *p1 = p->u.array.u.uint64_ptr; - uint64_t *p2 = p1 + len - 1; - while (p1 < p2) { - uint64_t v = *p1; - *p1++ = *p2; - *p2-- = v; - } - } - break; - default: - abort(); - } - } - return JS_DupValue(ctx, this_val); -} - -static JSValue js_typed_array_toReversed(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue arr, ret; - JSObject *p; - - p = get_typed_array(ctx, this_val, /*is_dataview*/0); - if (!p) - return JS_EXCEPTION; - arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val, - p->class_id); - if (JS_IsException(arr)) - return JS_EXCEPTION; - ret = js_typed_array_reverse(ctx, arr, argc, argv); - JS_FreeValue(ctx, arr); - return ret; -} - -static void slice_memcpy(uint8_t *dst, const uint8_t *src, size_t len) -{ - if (dst + len <= src || dst >= src + len) { - /* no overlap: can use memcpy */ - memcpy(dst, src, len); - } else { - /* otherwise the spec mandates byte copy */ - while (len-- != 0) - *dst++ = *src++; - } -} - -static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValueConst args[2]; - JSValue arr, val; - JSObject *p, *p1; - int n, len, start, final, count, shift; - - arr = JS_UNDEFINED; - len = js_typed_array_get_length_internal(ctx, this_val); - if (len < 0) - goto exception; - - if (JS_ToInt32Clamp(ctx, &start, argv[0], 0, len, len)) - goto exception; - final = len; - if (!JS_IsUndefined(argv[1])) { - if (JS_ToInt32Clamp(ctx, &final, argv[1], 0, len, len)) - goto exception; - } - count = max_int(final - start, 0); - - p = get_typed_array(ctx, this_val, 0); - if (p == NULL) - goto exception; - shift = typed_array_size_log2(p->class_id); - - args[0] = this_val; - args[1] = JS_NewInt32(ctx, count); - arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args); - if (JS_IsException(arr)) - goto exception; - - if (count > 0) { - if (validate_typed_array(ctx, this_val) - || validate_typed_array(ctx, arr)) - goto exception; - - p1 = get_typed_array(ctx, arr, 0); - if (p1 != NULL && p->class_id == p1->class_id && - typed_array_get_length(ctx, p1) >= count && - typed_array_get_length(ctx, p) >= start + count) { - slice_memcpy(p1->u.array.u.uint8_ptr, - p->u.array.u.uint8_ptr + (start << shift), - count << shift); - } else { - for (n = 0; n < count; n++) { - val = JS_GetPropertyValue(ctx, this_val, JS_NewInt32(ctx, start + n)); - if (JS_IsException(val)) - goto exception; - if (JS_SetPropertyValue(ctx, arr, JS_NewInt32(ctx, n), val, - JS_PROP_THROW) < 0) - goto exception; - } - } - } - return arr; - - exception: - JS_FreeValue(ctx, arr); - return JS_EXCEPTION; -} - -static JSValue js_typed_array_subarray(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValueConst args[4]; - JSValue arr, byteOffset, ta_buffer; - JSObject *p; - int len, start, final, count, shift, offset; - - p = get_typed_array(ctx, this_val, 0); - if (!p) - goto exception; - len = p->u.array.count; - if (JS_ToInt32Clamp(ctx, &start, argv[0], 0, len, len)) - goto exception; - - final = len; - if (!JS_IsUndefined(argv[1])) { - if (JS_ToInt32Clamp(ctx, &final, argv[1], 0, len, len)) - goto exception; - } - count = max_int(final - start, 0); - byteOffset = js_typed_array_get_byteOffset(ctx, this_val, 0); - if (JS_IsException(byteOffset)) - goto exception; - shift = typed_array_size_log2(p->class_id); - offset = JS_VALUE_GET_INT(byteOffset) + (start << shift); - JS_FreeValue(ctx, byteOffset); - ta_buffer = js_typed_array_get_buffer(ctx, this_val, 0); - if (JS_IsException(ta_buffer)) - goto exception; - args[0] = this_val; - args[1] = ta_buffer; - args[2] = JS_NewInt32(ctx, offset); - args[3] = JS_NewInt32(ctx, count); - arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 4, args); - JS_FreeValue(ctx, ta_buffer); - return arr; - - exception: - return JS_EXCEPTION; -} - -/* TypedArray.prototype.sort */ - -static int js_cmp_doubles(double x, double y) -{ - if (isnan(x)) return isnan(y) ? 0 : +1; - if (isnan(y)) return -1; - if (x < y) return -1; - if (x > y) return 1; - if (x != 0) return 0; - if (signbit(x)) return signbit(y) ? 0 : -1; - else return signbit(y) ? 1 : 0; -} - -static int js_TA_cmp_int8(const void *a, const void *b, void *opaque) { - return *(const int8_t *)a - *(const int8_t *)b; -} - -static int js_TA_cmp_uint8(const void *a, const void *b, void *opaque) { - return *(const uint8_t *)a - *(const uint8_t *)b; -} - -static int js_TA_cmp_int16(const void *a, const void *b, void *opaque) { - return *(const int16_t *)a - *(const int16_t *)b; -} - -static int js_TA_cmp_uint16(const void *a, const void *b, void *opaque) { - return *(const uint16_t *)a - *(const uint16_t *)b; -} - -static int js_TA_cmp_int32(const void *a, const void *b, void *opaque) { - int32_t x = *(const int32_t *)a; - int32_t y = *(const int32_t *)b; - return (y < x) - (y > x); -} - -static int js_TA_cmp_uint32(const void *a, const void *b, void *opaque) { - uint32_t x = *(const uint32_t *)a; - uint32_t y = *(const uint32_t *)b; - return (y < x) - (y > x); -} - -static int js_TA_cmp_int64(const void *a, const void *b, void *opaque) { - int64_t x = *(const int64_t *)a; - int64_t y = *(const int64_t *)b; - return (y < x) - (y > x); -} - -static int js_TA_cmp_uint64(const void *a, const void *b, void *opaque) { - uint64_t x = *(const uint64_t *)a; - uint64_t y = *(const uint64_t *)b; - return (y < x) - (y > x); -} - -static int js_TA_cmp_float16(const void *a, const void *b, void *opaque) { - return js_cmp_doubles(fromfp16(*(const uint16_t *)a), - fromfp16(*(const uint16_t *)b)); -} - -static int js_TA_cmp_float32(const void *a, const void *b, void *opaque) { - return js_cmp_doubles(*(const float *)a, *(const float *)b); -} - -static int js_TA_cmp_float64(const void *a, const void *b, void *opaque) { - return js_cmp_doubles(*(const double *)a, *(const double *)b); -} - -static JSValue js_TA_get_int8(JSContext *ctx, const void *a) { - return JS_NewInt32(ctx, *(const int8_t *)a); -} - -static JSValue js_TA_get_uint8(JSContext *ctx, const void *a) { - return JS_NewInt32(ctx, *(const uint8_t *)a); -} - -static JSValue js_TA_get_int16(JSContext *ctx, const void *a) { - return JS_NewInt32(ctx, *(const int16_t *)a); -} - -static JSValue js_TA_get_uint16(JSContext *ctx, const void *a) { - return JS_NewInt32(ctx, *(const uint16_t *)a); -} - -static JSValue js_TA_get_int32(JSContext *ctx, const void *a) { - return JS_NewInt32(ctx, *(const int32_t *)a); -} - -static JSValue js_TA_get_uint32(JSContext *ctx, const void *a) { - return JS_NewUint32(ctx, *(const uint32_t *)a); -} - -static JSValue js_TA_get_int64(JSContext *ctx, const void *a) { - return JS_NewBigInt64(ctx, *(int64_t *)a); -} - -static JSValue js_TA_get_uint64(JSContext *ctx, const void *a) { - return JS_NewBigUint64(ctx, *(uint64_t *)a); -} - -static JSValue js_TA_get_float16(JSContext *ctx, const void *a) { - return __JS_NewFloat64(ctx, fromfp16(*(const uint16_t *)a)); -} - -static JSValue js_TA_get_float32(JSContext *ctx, const void *a) { - return __JS_NewFloat64(ctx, *(const float *)a); -} - -static JSValue js_TA_get_float64(JSContext *ctx, const void *a) { - return __JS_NewFloat64(ctx, *(const double *)a); -} - -struct TA_sort_context { - JSContext *ctx; - int exception; /* 1 = exception, 2 = detached typed array */ - JSValueConst arr; - JSValueConst cmp; - JSValue (*getfun)(JSContext *ctx, const void *a); - uint8_t *array_ptr; /* cannot change unless the array is detached */ - int elt_size; -}; - -static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) { - struct TA_sort_context *psc = opaque; - JSContext *ctx = psc->ctx; - uint32_t a_idx, b_idx; - JSValueConst argv[2]; - JSValue res; - int cmp; - - cmp = 0; - if (!psc->exception) { - /* Note: the typed array can be detached without causing an - error */ - a_idx = *(uint32_t *)a; - b_idx = *(uint32_t *)b; - argv[0] = psc->getfun(ctx, psc->array_ptr + - a_idx * (size_t)psc->elt_size); - argv[1] = psc->getfun(ctx, psc->array_ptr + - b_idx * (size_t)(psc->elt_size)); - res = JS_Call(ctx, psc->cmp, JS_UNDEFINED, 2, argv); - if (JS_IsException(res)) { - psc->exception = 1; - goto done; - } - if (JS_VALUE_GET_TAG(res) == JS_TAG_INT) { - int val = JS_VALUE_GET_INT(res); - cmp = (val > 0) - (val < 0); - } else { - double val; - if (JS_ToFloat64Free(ctx, &val, res) < 0) { - psc->exception = 1; - goto done; - } else { - cmp = (val > 0) - (val < 0); - } - } - if (cmp == 0) { - /* make sort stable: compare array offsets */ - cmp = (a_idx > b_idx) - (a_idx < b_idx); - } - if (unlikely(typed_array_is_detached(ctx, - JS_VALUE_GET_PTR(psc->arr)))) { - psc->exception = 2; - } - done: - JS_FreeValue(ctx, (JSValue)argv[0]); - JS_FreeValue(ctx, (JSValue)argv[1]); - } - return cmp; -} - -static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSObject *p; - int len; - size_t elt_size; - struct TA_sort_context tsc; - void *array_ptr; - int (*cmpfun)(const void *a, const void *b, void *opaque); - - tsc.ctx = ctx; - tsc.exception = 0; - tsc.arr = this_val; - tsc.cmp = argv[0]; - - if (!JS_IsUndefined(tsc.cmp) && check_function(ctx, tsc.cmp)) - return JS_EXCEPTION; - len = js_typed_array_get_length_internal(ctx, this_val); - if (len < 0) - return JS_EXCEPTION; - - if (len > 1) { - p = JS_VALUE_GET_OBJ(this_val); - switch (p->class_id) { - case JS_CLASS_INT8_ARRAY: - tsc.getfun = js_TA_get_int8; - cmpfun = js_TA_cmp_int8; - break; - case JS_CLASS_UINT8C_ARRAY: - case JS_CLASS_UINT8_ARRAY: - tsc.getfun = js_TA_get_uint8; - cmpfun = js_TA_cmp_uint8; - break; - case JS_CLASS_INT16_ARRAY: - tsc.getfun = js_TA_get_int16; - cmpfun = js_TA_cmp_int16; - break; - case JS_CLASS_UINT16_ARRAY: - tsc.getfun = js_TA_get_uint16; - cmpfun = js_TA_cmp_uint16; - break; - case JS_CLASS_INT32_ARRAY: - tsc.getfun = js_TA_get_int32; - cmpfun = js_TA_cmp_int32; - break; - case JS_CLASS_UINT32_ARRAY: - tsc.getfun = js_TA_get_uint32; - cmpfun = js_TA_cmp_uint32; - break; - case JS_CLASS_BIG_INT64_ARRAY: - tsc.getfun = js_TA_get_int64; - cmpfun = js_TA_cmp_int64; - break; - case JS_CLASS_BIG_UINT64_ARRAY: - tsc.getfun = js_TA_get_uint64; - cmpfun = js_TA_cmp_uint64; - break; - case JS_CLASS_FLOAT16_ARRAY: - tsc.getfun = js_TA_get_float16; - cmpfun = js_TA_cmp_float16; - break; - case JS_CLASS_FLOAT32_ARRAY: - tsc.getfun = js_TA_get_float32; - cmpfun = js_TA_cmp_float32; - break; - case JS_CLASS_FLOAT64_ARRAY: - tsc.getfun = js_TA_get_float64; - cmpfun = js_TA_cmp_float64; - break; - default: - abort(); - } - array_ptr = p->u.array.u.ptr; - elt_size = 1 << typed_array_size_log2(p->class_id); - if (!JS_IsUndefined(tsc.cmp)) { - uint32_t *array_idx; - void *array_tmp; - size_t i, j; - - /* XXX: a stable sort would use less memory */ - array_idx = js_malloc(ctx, len * sizeof(array_idx[0])); - if (!array_idx) - return JS_EXCEPTION; - for(i = 0; i < len; i++) - array_idx[i] = i; - tsc.array_ptr = array_ptr; - tsc.elt_size = elt_size; - rqsort(array_idx, len, sizeof(array_idx[0]), - js_TA_cmp_generic, &tsc); - if (tsc.exception) { - if (tsc.exception == 1) - goto fail; - /* detached typed array during the sort: no error */ - } else { - array_tmp = js_malloc(ctx, len * elt_size); - if (!array_tmp) { - fail: - js_free(ctx, array_idx); - return JS_EXCEPTION; - } - memcpy(array_tmp, array_ptr, len * elt_size); - switch(elt_size) { - case 1: - for(i = 0; i < len; i++) { - j = array_idx[i]; - ((uint8_t *)array_ptr)[i] = ((uint8_t *)array_tmp)[j]; - } - break; - case 2: - for(i = 0; i < len; i++) { - j = array_idx[i]; - ((uint16_t *)array_ptr)[i] = ((uint16_t *)array_tmp)[j]; - } - break; - case 4: - for(i = 0; i < len; i++) { - j = array_idx[i]; - ((uint32_t *)array_ptr)[i] = ((uint32_t *)array_tmp)[j]; - } - break; - case 8: - for(i = 0; i < len; i++) { - j = array_idx[i]; - ((uint64_t *)array_ptr)[i] = ((uint64_t *)array_tmp)[j]; - } - break; - default: - abort(); - } - js_free(ctx, array_tmp); - } - js_free(ctx, array_idx); - } else { - rqsort(array_ptr, len, elt_size, cmpfun, &tsc); - if (tsc.exception) - return JS_EXCEPTION; - } - } - return JS_DupValue(ctx, this_val); -} - -static JSValue js_typed_array_toSorted(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue arr, ret; - JSObject *p; - - p = get_typed_array(ctx, this_val, /*is_dataview*/0); - if (!p) - return JS_EXCEPTION; - arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val, - p->class_id); - if (JS_IsException(arr)) - return JS_EXCEPTION; - ret = js_typed_array_sort(ctx, arr, argc, argv); - JS_FreeValue(ctx, arr); - return ret; -} - -static const JSCFunctionListEntry js_typed_array_base_funcs[] = { - JS_CFUNC_DEF("from", 1, js_typed_array_from ), - JS_CFUNC_DEF("of", 0, js_typed_array_of ), - JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ), - //JS_CFUNC_DEF("__getLength", 2, js_typed_array___getLength ), - //JS_CFUNC_DEF("__create", 2, js_typed_array___create ), - //JS_CFUNC_DEF("__speciesCreate", 2, js_typed_array___speciesCreate ), -}; - -static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = { - JS_CGETSET_DEF("length", js_typed_array_get_length, NULL ), - JS_CFUNC_DEF("at", 1, js_typed_array_at ), - JS_CFUNC_DEF("with", 2, js_typed_array_with ), - JS_CGETSET_MAGIC_DEF("buffer", js_typed_array_get_buffer, NULL, 0 ), - JS_CGETSET_MAGIC_DEF("byteLength", js_typed_array_get_byteLength, NULL, 0 ), - JS_CGETSET_MAGIC_DEF("byteOffset", js_typed_array_get_byteOffset, NULL, 0 ), - JS_CFUNC_DEF("set", 1, js_typed_array_set ), - JS_CFUNC_MAGIC_DEF("values", 0, js_create_typed_array_iterator, JS_ITERATOR_KIND_VALUE ), - JS_ALIAS_DEF("[Symbol.iterator]", "values" ), - JS_CFUNC_MAGIC_DEF("keys", 0, js_create_typed_array_iterator, JS_ITERATOR_KIND_KEY ), - JS_CFUNC_MAGIC_DEF("entries", 0, js_create_typed_array_iterator, JS_ITERATOR_KIND_KEY_AND_VALUE ), - JS_CGETSET_DEF("[Symbol.toStringTag]", js_typed_array_get_toStringTag, NULL ), - JS_CFUNC_DEF("copyWithin", 2, js_typed_array_copyWithin ), - JS_CFUNC_MAGIC_DEF("every", 1, js_array_every, special_every | special_TA ), - JS_CFUNC_MAGIC_DEF("some", 1, js_array_every, special_some | special_TA ), - JS_CFUNC_MAGIC_DEF("forEach", 1, js_array_every, special_forEach | special_TA ), - JS_CFUNC_MAGIC_DEF("map", 1, js_array_every, special_map | special_TA ), - JS_CFUNC_MAGIC_DEF("filter", 1, js_array_every, special_filter | special_TA ), - JS_CFUNC_MAGIC_DEF("reduce", 1, js_array_reduce, special_reduce | special_TA ), - JS_CFUNC_MAGIC_DEF("reduceRight", 1, js_array_reduce, special_reduceRight | special_TA ), - JS_CFUNC_DEF("fill", 1, js_typed_array_fill ), - JS_CFUNC_MAGIC_DEF("find", 1, js_typed_array_find, ArrayFind ), - JS_CFUNC_MAGIC_DEF("findIndex", 1, js_typed_array_find, ArrayFindIndex ), - JS_CFUNC_MAGIC_DEF("findLast", 1, js_typed_array_find, ArrayFindLast ), - JS_CFUNC_MAGIC_DEF("findLastIndex", 1, js_typed_array_find, ArrayFindLastIndex ), - JS_CFUNC_DEF("reverse", 0, js_typed_array_reverse ), - JS_CFUNC_DEF("toReversed", 0, js_typed_array_toReversed ), - JS_CFUNC_DEF("slice", 2, js_typed_array_slice ), - JS_CFUNC_DEF("subarray", 2, js_typed_array_subarray ), - JS_CFUNC_DEF("sort", 1, js_typed_array_sort ), - JS_CFUNC_DEF("toSorted", 1, js_typed_array_toSorted ), - JS_CFUNC_MAGIC_DEF("join", 1, js_typed_array_join, 0 ), - JS_CFUNC_MAGIC_DEF("toLocaleString", 0, js_typed_array_join, 1 ), - JS_CFUNC_MAGIC_DEF("indexOf", 1, js_typed_array_indexOf, special_indexOf ), - JS_CFUNC_MAGIC_DEF("lastIndexOf", 1, js_typed_array_indexOf, special_lastIndexOf ), - JS_CFUNC_MAGIC_DEF("includes", 1, js_typed_array_indexOf, special_includes ), - //JS_ALIAS_BASE_DEF("toString", "toString", 2 /* Array.prototype. */), @@@ -}; - -static JSValue js_typed_array_base_constructor(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv) -{ - return JS_ThrowTypeError(ctx, "cannot be called"); -} - -/* 'obj' must be an allocated typed array object */ -static int typed_array_init(JSContext *ctx, JSValueConst obj, - JSValue buffer, uint64_t offset, uint64_t len) -{ - JSTypedArray *ta; - JSObject *p, *pbuffer; - JSArrayBuffer *abuf; - int size_log2; - - p = JS_VALUE_GET_OBJ(obj); - size_log2 = typed_array_size_log2(p->class_id); - ta = js_malloc(ctx, sizeof(*ta)); - if (!ta) { - JS_FreeValue(ctx, buffer); - return -1; - } - pbuffer = JS_VALUE_GET_OBJ(buffer); - abuf = pbuffer->u.array_buffer; - ta->obj = p; - ta->buffer = pbuffer; - ta->offset = offset; - ta->length = len << size_log2; - list_add_tail(&ta->link, &abuf->array_list); - p->u.typed_array = ta; - p->u.array.count = len; - p->u.array.u.ptr = abuf->data + offset; - return 0; -} - - -static JSValue js_array_from_iterator(JSContext *ctx, uint32_t *plen, - JSValueConst obj, JSValueConst method) -{ - JSValue arr, iter, next_method = JS_UNDEFINED, val; - BOOL done; - uint32_t k; - - *plen = 0; - arr = JS_NewArray(ctx); - if (JS_IsException(arr)) - return arr; - iter = JS_GetIterator2(ctx, obj, method); - if (JS_IsException(iter)) - goto fail; - next_method = JS_GetProperty(ctx, iter, JS_ATOM_next); - if (JS_IsException(next_method)) - goto fail; - k = 0; - for(;;) { - val = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done); - if (JS_IsException(val)) - goto fail; - if (done) - break; - if (JS_CreateDataPropertyUint32(ctx, arr, k, val, JS_PROP_THROW) < 0) - goto fail; - k++; - } - JS_FreeValue(ctx, next_method); - JS_FreeValue(ctx, iter); - *plen = k; - return arr; - fail: - JS_FreeValue(ctx, next_method); - JS_FreeValue(ctx, iter); - JS_FreeValue(ctx, arr); - return JS_EXCEPTION; -} - -static JSValue js_typed_array_constructor_obj(JSContext *ctx, - JSValueConst new_target, - JSValueConst obj, - int classid) -{ - JSValue iter, ret, arr = JS_UNDEFINED, val, buffer; - uint32_t i; - int size_log2; - int64_t len; - - size_log2 = typed_array_size_log2(classid); - ret = js_create_from_ctor(ctx, new_target, classid); - if (JS_IsException(ret)) - return JS_EXCEPTION; - - iter = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator); - if (JS_IsException(iter)) - goto fail; - if (!JS_IsUndefined(iter) && !JS_IsNull(iter)) { - uint32_t len1; - arr = js_array_from_iterator(ctx, &len1, obj, iter); - JS_FreeValue(ctx, iter); - if (JS_IsException(arr)) - goto fail; - len = len1; - } else { - if (js_get_length64(ctx, &len, obj)) - goto fail; - arr = JS_DupValue(ctx, obj); - } - - buffer = js_array_buffer_constructor1(ctx, JS_UNDEFINED, - len << size_log2); - if (JS_IsException(buffer)) - goto fail; - if (typed_array_init(ctx, ret, buffer, 0, len)) - goto fail; - - for(i = 0; i < len; i++) { - val = JS_GetPropertyUint32(ctx, arr, i); - if (JS_IsException(val)) - goto fail; - if (JS_SetPropertyUint32(ctx, ret, i, val) < 0) - goto fail; - } - JS_FreeValue(ctx, arr); - return ret; - fail: - JS_FreeValue(ctx, arr); - JS_FreeValue(ctx, ret); - return JS_EXCEPTION; -} - -static JSValue js_typed_array_constructor_ta(JSContext *ctx, - JSValueConst new_target, - JSValueConst src_obj, - int classid) -{ - JSObject *p, *src_buffer; - JSTypedArray *ta; - JSValue obj, buffer; - uint32_t len, i; - int size_log2; - JSArrayBuffer *src_abuf, *abuf; - - obj = js_create_from_ctor(ctx, new_target, classid); - if (JS_IsException(obj)) - return obj; - p = JS_VALUE_GET_OBJ(src_obj); - if (typed_array_is_detached(ctx, p)) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - goto fail; - } - ta = p->u.typed_array; - len = p->u.array.count; - src_buffer = ta->buffer; - src_abuf = src_buffer->u.array_buffer; - size_log2 = typed_array_size_log2(classid); - buffer = js_array_buffer_constructor1(ctx, JS_UNDEFINED, - (uint64_t)len << size_log2); - if (JS_IsException(buffer)) - goto fail; - /* necessary because it could have been detached */ - if (typed_array_is_detached(ctx, p)) { - JS_FreeValue(ctx, buffer); - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - goto fail; - } - abuf = JS_GetOpaque(buffer, JS_CLASS_ARRAY_BUFFER); - if (typed_array_init(ctx, obj, buffer, 0, len)) - goto fail; - if (p->class_id == classid) { - /* same type: copy the content */ - memcpy(abuf->data, src_abuf->data + ta->offset, abuf->byte_length); - } else { - for(i = 0; i < len; i++) { - JSValue val; - val = JS_GetPropertyUint32(ctx, src_obj, i); - if (JS_IsException(val)) - goto fail; - if (JS_SetPropertyUint32(ctx, obj, i, val) < 0) - goto fail; - } - } - return obj; - fail: - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; -} - -static JSValue js_typed_array_constructor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv, - int classid) -{ - JSValue buffer, obj; - JSArrayBuffer *abuf; - int size_log2; - uint64_t len, offset; - - size_log2 = typed_array_size_log2(classid); - if (JS_VALUE_GET_TAG(argv[0]) != JS_TAG_OBJECT) { - if (JS_ToIndex(ctx, &len, argv[0])) - return JS_EXCEPTION; - buffer = js_array_buffer_constructor1(ctx, JS_UNDEFINED, - len << size_log2); - if (JS_IsException(buffer)) - return JS_EXCEPTION; - offset = 0; - } else { - JSObject *p = JS_VALUE_GET_OBJ(argv[0]); - if (p->class_id == JS_CLASS_ARRAY_BUFFER || - p->class_id == JS_CLASS_SHARED_ARRAY_BUFFER) { - abuf = p->u.array_buffer; - if (JS_ToIndex(ctx, &offset, argv[1])) - return JS_EXCEPTION; - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - if ((offset & ((1 << size_log2) - 1)) != 0 || - offset > abuf->byte_length) - return JS_ThrowRangeError(ctx, "invalid offset"); - if (JS_IsUndefined(argv[2])) { - if ((abuf->byte_length & ((1 << size_log2) - 1)) != 0) - goto invalid_length; - len = (abuf->byte_length - offset) >> size_log2; - } else { - if (JS_ToIndex(ctx, &len, argv[2])) - return JS_EXCEPTION; - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - if ((offset + (len << size_log2)) > abuf->byte_length) { - invalid_length: - return JS_ThrowRangeError(ctx, "invalid length"); - } - } - buffer = JS_DupValue(ctx, argv[0]); - } else { - if (p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_FLOAT64_ARRAY) { - return js_typed_array_constructor_ta(ctx, new_target, argv[0], classid); - } else { - return js_typed_array_constructor_obj(ctx, new_target, argv[0], classid); - } - } - } - - obj = js_create_from_ctor(ctx, new_target, classid); - if (JS_IsException(obj)) { - JS_FreeValue(ctx, buffer); - return JS_EXCEPTION; - } - if (typed_array_init(ctx, obj, buffer, offset, len)) { - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } - return obj; -} - -static void js_typed_array_finalizer(JSRuntime *rt, JSValue val) -{ - JSObject *p = JS_VALUE_GET_OBJ(val); - JSTypedArray *ta = p->u.typed_array; - if (ta) { - /* during the GC the finalizers are called in an arbitrary - order so the ArrayBuffer finalizer may have been called */ - if (ta->link.next) { - list_del(&ta->link); - } - JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, ta->buffer)); - js_free_rt(rt, ta); - } -} - -static void js_typed_array_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func) -{ - JSObject *p = JS_VALUE_GET_OBJ(val); - JSTypedArray *ta = p->u.typed_array; - if (ta) { - JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, ta->buffer), mark_func); - } -} - -static JSValue js_dataview_constructor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv) -{ - JSArrayBuffer *abuf; - uint64_t offset; - uint32_t len; - JSValueConst buffer; - JSValue obj; - JSTypedArray *ta; - JSObject *p; - - buffer = argv[0]; - abuf = js_get_array_buffer(ctx, buffer); - if (!abuf) - return JS_EXCEPTION; - offset = 0; - if (argc > 1) { - if (JS_ToIndex(ctx, &offset, argv[1])) - return JS_EXCEPTION; - } - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - if (offset > abuf->byte_length) - return JS_ThrowRangeError(ctx, "invalid byteOffset"); - len = abuf->byte_length - offset; - if (argc > 2 && !JS_IsUndefined(argv[2])) { - uint64_t l; - if (JS_ToIndex(ctx, &l, argv[2])) - return JS_EXCEPTION; - if (l > len) - return JS_ThrowRangeError(ctx, "invalid byteLength"); - len = l; - } - - obj = js_create_from_ctor(ctx, new_target, JS_CLASS_DATAVIEW); - if (JS_IsException(obj)) - return JS_EXCEPTION; - if (abuf->detached) { - /* could have been detached in js_create_from_ctor() */ - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - goto fail; - } - ta = js_malloc(ctx, sizeof(*ta)); - if (!ta) { - fail: - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } - p = JS_VALUE_GET_OBJ(obj); - ta->obj = p; - ta->buffer = JS_VALUE_GET_OBJ(JS_DupValue(ctx, buffer)); - ta->offset = offset; - ta->length = len; - list_add_tail(&ta->link, &abuf->array_list); - p->u.typed_array = ta; - return obj; -} - -static JSValue js_dataview_getValue(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv, int class_id) -{ - JSTypedArray *ta; - JSArrayBuffer *abuf; - BOOL littleEndian, is_swap; - int size; - uint8_t *ptr; - uint32_t v; - uint64_t pos; - - ta = JS_GetOpaque2(ctx, this_obj, JS_CLASS_DATAVIEW); - if (!ta) - return JS_EXCEPTION; - size = 1 << typed_array_size_log2(class_id); - if (JS_ToIndex(ctx, &pos, argv[0])) - return JS_EXCEPTION; - littleEndian = argc > 1 && JS_ToBool(ctx, argv[1]); - is_swap = littleEndian ^ !is_be(); - abuf = ta->buffer->u.array_buffer; - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - if ((pos + size) > ta->length) - return JS_ThrowRangeError(ctx, "out of bound"); - ptr = abuf->data + ta->offset + pos; - - switch(class_id) { - case JS_CLASS_INT8_ARRAY: - return JS_NewInt32(ctx, *(int8_t *)ptr); - case JS_CLASS_UINT8_ARRAY: - return JS_NewInt32(ctx, *(uint8_t *)ptr); - case JS_CLASS_INT16_ARRAY: - v = get_u16(ptr); - if (is_swap) - v = bswap16(v); - return JS_NewInt32(ctx, (int16_t)v); - case JS_CLASS_UINT16_ARRAY: - v = get_u16(ptr); - if (is_swap) - v = bswap16(v); - return JS_NewInt32(ctx, v); - case JS_CLASS_INT32_ARRAY: - v = get_u32(ptr); - if (is_swap) - v = bswap32(v); - return JS_NewInt32(ctx, v); - case JS_CLASS_UINT32_ARRAY: - v = get_u32(ptr); - if (is_swap) - v = bswap32(v); - return JS_NewUint32(ctx, v); - case JS_CLASS_BIG_INT64_ARRAY: - { - uint64_t v; - v = get_u64(ptr); - if (is_swap) - v = bswap64(v); - return JS_NewBigInt64(ctx, v); - } - break; - case JS_CLASS_BIG_UINT64_ARRAY: - { - uint64_t v; - v = get_u64(ptr); - if (is_swap) - v = bswap64(v); - return JS_NewBigUint64(ctx, v); - } - break; - case JS_CLASS_FLOAT16_ARRAY: - { - uint16_t v; - v = get_u16(ptr); - if (is_swap) - v = bswap16(v); - return __JS_NewFloat64(ctx, fromfp16(v)); - } - case JS_CLASS_FLOAT32_ARRAY: - { - union { - float f; - uint32_t i; - } u; - v = get_u32(ptr); - if (is_swap) - v = bswap32(v); - u.i = v; - return __JS_NewFloat64(ctx, u.f); - } - case JS_CLASS_FLOAT64_ARRAY: - { - union { - double f; - uint64_t i; - } u; - u.i = get_u64(ptr); - if (is_swap) - u.i = bswap64(u.i); - return __JS_NewFloat64(ctx, u.f); - } - default: - abort(); - } -} - -static JSValue js_dataview_setValue(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv, int class_id) -{ - JSTypedArray *ta; - JSArrayBuffer *abuf; - BOOL littleEndian, is_swap; - int size; - uint8_t *ptr; - uint64_t v64; - uint32_t v; - uint64_t pos; - JSValueConst val; - - ta = JS_GetOpaque2(ctx, this_obj, JS_CLASS_DATAVIEW); - if (!ta) - return JS_EXCEPTION; - size = 1 << typed_array_size_log2(class_id); - if (JS_ToIndex(ctx, &pos, argv[0])) - return JS_EXCEPTION; - val = argv[1]; - v = 0; /* avoid warning */ - v64 = 0; /* avoid warning */ - if (class_id <= JS_CLASS_UINT32_ARRAY) { - if (JS_ToUint32(ctx, &v, val)) - return JS_EXCEPTION; - } else if (class_id <= JS_CLASS_BIG_UINT64_ARRAY) { - if (JS_ToBigInt64(ctx, (int64_t *)&v64, val)) - return JS_EXCEPTION; - } else { - double d; - if (JS_ToFloat64(ctx, &d, val)) - return JS_EXCEPTION; - if (class_id == JS_CLASS_FLOAT16_ARRAY) { - v = tofp16(d); - } else if (class_id == JS_CLASS_FLOAT32_ARRAY) { - union { - float f; - uint32_t i; - } u; - u.f = d; - v = u.i; - } else { - JSFloat64Union u; - u.d = d; - v64 = u.u64; - } - } - littleEndian = argc > 2 && JS_ToBool(ctx, argv[2]); - is_swap = littleEndian ^ !is_be(); - abuf = ta->buffer->u.array_buffer; - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - if ((pos + size) > ta->length) - return JS_ThrowRangeError(ctx, "out of bound"); - ptr = abuf->data + ta->offset + pos; - - switch(class_id) { - case JS_CLASS_INT8_ARRAY: - case JS_CLASS_UINT8_ARRAY: - *ptr = v; - break; - case JS_CLASS_INT16_ARRAY: - case JS_CLASS_UINT16_ARRAY: - case JS_CLASS_FLOAT16_ARRAY: - if (is_swap) - v = bswap16(v); - put_u16(ptr, v); - break; - case JS_CLASS_INT32_ARRAY: - case JS_CLASS_UINT32_ARRAY: - case JS_CLASS_FLOAT32_ARRAY: - if (is_swap) - v = bswap32(v); - put_u32(ptr, v); - break; - case JS_CLASS_BIG_INT64_ARRAY: - case JS_CLASS_BIG_UINT64_ARRAY: - case JS_CLASS_FLOAT64_ARRAY: - if (is_swap) - v64 = bswap64(v64); - put_u64(ptr, v64); - break; - default: - abort(); - } - return JS_UNDEFINED; -} - -static const JSCFunctionListEntry js_dataview_proto_funcs[] = { - JS_CGETSET_MAGIC_DEF("buffer", js_typed_array_get_buffer, NULL, 1 ), - JS_CGETSET_MAGIC_DEF("byteLength", js_typed_array_get_byteLength, NULL, 1 ), - JS_CGETSET_MAGIC_DEF("byteOffset", js_typed_array_get_byteOffset, NULL, 1 ), - JS_CFUNC_MAGIC_DEF("getInt8", 1, js_dataview_getValue, JS_CLASS_INT8_ARRAY ), - JS_CFUNC_MAGIC_DEF("getUint8", 1, js_dataview_getValue, JS_CLASS_UINT8_ARRAY ), - JS_CFUNC_MAGIC_DEF("getInt16", 1, js_dataview_getValue, JS_CLASS_INT16_ARRAY ), - JS_CFUNC_MAGIC_DEF("getUint16", 1, js_dataview_getValue, JS_CLASS_UINT16_ARRAY ), - JS_CFUNC_MAGIC_DEF("getInt32", 1, js_dataview_getValue, JS_CLASS_INT32_ARRAY ), - JS_CFUNC_MAGIC_DEF("getUint32", 1, js_dataview_getValue, JS_CLASS_UINT32_ARRAY ), - JS_CFUNC_MAGIC_DEF("getBigInt64", 1, js_dataview_getValue, JS_CLASS_BIG_INT64_ARRAY ), - JS_CFUNC_MAGIC_DEF("getBigUint64", 1, js_dataview_getValue, JS_CLASS_BIG_UINT64_ARRAY ), - JS_CFUNC_MAGIC_DEF("getFloat16", 1, js_dataview_getValue, JS_CLASS_FLOAT16_ARRAY ), - JS_CFUNC_MAGIC_DEF("getFloat32", 1, js_dataview_getValue, JS_CLASS_FLOAT32_ARRAY ), - JS_CFUNC_MAGIC_DEF("getFloat64", 1, js_dataview_getValue, JS_CLASS_FLOAT64_ARRAY ), - JS_CFUNC_MAGIC_DEF("setInt8", 2, js_dataview_setValue, JS_CLASS_INT8_ARRAY ), - JS_CFUNC_MAGIC_DEF("setUint8", 2, js_dataview_setValue, JS_CLASS_UINT8_ARRAY ), - JS_CFUNC_MAGIC_DEF("setInt16", 2, js_dataview_setValue, JS_CLASS_INT16_ARRAY ), - JS_CFUNC_MAGIC_DEF("setUint16", 2, js_dataview_setValue, JS_CLASS_UINT16_ARRAY ), - JS_CFUNC_MAGIC_DEF("setInt32", 2, js_dataview_setValue, JS_CLASS_INT32_ARRAY ), - JS_CFUNC_MAGIC_DEF("setUint32", 2, js_dataview_setValue, JS_CLASS_UINT32_ARRAY ), - JS_CFUNC_MAGIC_DEF("setBigInt64", 2, js_dataview_setValue, JS_CLASS_BIG_INT64_ARRAY ), - JS_CFUNC_MAGIC_DEF("setBigUint64", 2, js_dataview_setValue, JS_CLASS_BIG_UINT64_ARRAY ), - JS_CFUNC_MAGIC_DEF("setFloat16", 2, js_dataview_setValue, JS_CLASS_FLOAT16_ARRAY ), - JS_CFUNC_MAGIC_DEF("setFloat32", 2, js_dataview_setValue, JS_CLASS_FLOAT32_ARRAY ), - JS_CFUNC_MAGIC_DEF("setFloat64", 2, js_dataview_setValue, JS_CLASS_FLOAT64_ARRAY ), - JS_PROP_STRING_DEF("[Symbol.toStringTag]", "DataView", JS_PROP_CONFIGURABLE ), -}; - -/* Atomics */ -#ifdef CONFIG_ATOMICS - -typedef enum AtomicsOpEnum { - ATOMICS_OP_ADD, - ATOMICS_OP_AND, - ATOMICS_OP_OR, - ATOMICS_OP_SUB, - ATOMICS_OP_XOR, - ATOMICS_OP_EXCHANGE, - ATOMICS_OP_COMPARE_EXCHANGE, - ATOMICS_OP_LOAD, -} AtomicsOpEnum; - -static void *js_atomics_get_ptr(JSContext *ctx, - JSArrayBuffer **pabuf, - int *psize_log2, JSClassID *pclass_id, - JSValueConst obj, JSValueConst idx_val, - int is_waitable) -{ - JSObject *p; - JSTypedArray *ta; - JSArrayBuffer *abuf; - void *ptr; - uint64_t idx; - BOOL err; - int size_log2; - - if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) - goto fail; - p = JS_VALUE_GET_OBJ(obj); - if (is_waitable) - err = (p->class_id != JS_CLASS_INT32_ARRAY && - p->class_id != JS_CLASS_BIG_INT64_ARRAY); - else - err = !(p->class_id >= JS_CLASS_INT8_ARRAY && - p->class_id <= JS_CLASS_BIG_UINT64_ARRAY); - if (err) { - fail: - JS_ThrowTypeError(ctx, "integer TypedArray expected"); - return NULL; - } - ta = p->u.typed_array; - abuf = ta->buffer->u.array_buffer; - if (!abuf->shared) { - if (is_waitable == 2) { - JS_ThrowTypeError(ctx, "not a SharedArrayBuffer TypedArray"); - return NULL; - } - if (abuf->detached) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - return NULL; - } - } - if (JS_ToIndex(ctx, &idx, idx_val)) { - return NULL; - } - /* RevalidateAtomicAccess(): must test again detached after JS_ToIndex() */ - if (abuf->detached) { - JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - return NULL; - } - /* if the array buffer is detached, p->u.array.count = 0 */ - if (idx >= p->u.array.count) { - JS_ThrowRangeError(ctx, "out-of-bound access"); - return NULL; - } - size_log2 = typed_array_size_log2(p->class_id); - ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); - if (pabuf) - *pabuf = abuf; - if (psize_log2) - *psize_log2 = size_log2; - if (pclass_id) - *pclass_id = p->class_id; - return ptr; -} - -static JSValue js_atomics_op(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv, int op) -{ - int size_log2; - uint64_t v, a, rep_val; - void *ptr; - JSValue ret; - JSClassID class_id; - JSArrayBuffer *abuf; - - ptr = js_atomics_get_ptr(ctx, &abuf, &size_log2, &class_id, - argv[0], argv[1], 0); - if (!ptr) - return JS_EXCEPTION; - rep_val = 0; - if (op == ATOMICS_OP_LOAD) { - v = 0; - } else { - if (size_log2 == 3) { - int64_t v64; - if (JS_ToBigInt64(ctx, &v64, argv[2])) - return JS_EXCEPTION; - v = v64; - if (op == ATOMICS_OP_COMPARE_EXCHANGE) { - if (JS_ToBigInt64(ctx, &v64, argv[3])) - return JS_EXCEPTION; - rep_val = v64; - } - } else { - uint32_t v32; - if (JS_ToUint32(ctx, &v32, argv[2])) - return JS_EXCEPTION; - v = v32; - if (op == ATOMICS_OP_COMPARE_EXCHANGE) { - if (JS_ToUint32(ctx, &v32, argv[3])) - return JS_EXCEPTION; - rep_val = v32; - } - } - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - } - - switch(op | (size_log2 << 3)) { - -#define OP(op_name, func_name) \ - case ATOMICS_OP_ ## op_name | (0 << 3): \ - a = func_name((_Atomic(uint8_t) *)ptr, v); \ - break; \ - case ATOMICS_OP_ ## op_name | (1 << 3): \ - a = func_name((_Atomic(uint16_t) *)ptr, v); \ - break; \ - case ATOMICS_OP_ ## op_name | (2 << 3): \ - a = func_name((_Atomic(uint32_t) *)ptr, v); \ - break; \ - case ATOMICS_OP_ ## op_name | (3 << 3): \ - a = func_name((_Atomic(uint64_t) *)ptr, v); \ - break; - - OP(ADD, atomic_fetch_add) - OP(AND, atomic_fetch_and) - OP(OR, atomic_fetch_or) - OP(SUB, atomic_fetch_sub) - OP(XOR, atomic_fetch_xor) - OP(EXCHANGE, atomic_exchange) -#undef OP - - case ATOMICS_OP_LOAD | (0 << 3): - a = atomic_load((_Atomic(uint8_t) *)ptr); - break; - case ATOMICS_OP_LOAD | (1 << 3): - a = atomic_load((_Atomic(uint16_t) *)ptr); - break; - case ATOMICS_OP_LOAD | (2 << 3): - a = atomic_load((_Atomic(uint32_t) *)ptr); - break; - case ATOMICS_OP_LOAD | (3 << 3): - a = atomic_load((_Atomic(uint64_t) *)ptr); - break; - - case ATOMICS_OP_COMPARE_EXCHANGE | (0 << 3): - { - uint8_t v1 = v; - atomic_compare_exchange_strong((_Atomic(uint8_t) *)ptr, &v1, rep_val); - a = v1; - } - break; - case ATOMICS_OP_COMPARE_EXCHANGE | (1 << 3): - { - uint16_t v1 = v; - atomic_compare_exchange_strong((_Atomic(uint16_t) *)ptr, &v1, rep_val); - a = v1; - } - break; - case ATOMICS_OP_COMPARE_EXCHANGE | (2 << 3): - { - uint32_t v1 = v; - atomic_compare_exchange_strong((_Atomic(uint32_t) *)ptr, &v1, rep_val); - a = v1; - } - break; - case ATOMICS_OP_COMPARE_EXCHANGE | (3 << 3): - { - uint64_t v1 = v; - atomic_compare_exchange_strong((_Atomic(uint64_t) *)ptr, &v1, rep_val); - a = v1; - } - break; - default: - abort(); - } - - switch(class_id) { - case JS_CLASS_INT8_ARRAY: - a = (int8_t)a; - goto done; - case JS_CLASS_UINT8_ARRAY: - a = (uint8_t)a; - goto done; - case JS_CLASS_INT16_ARRAY: - a = (int16_t)a; - goto done; - case JS_CLASS_UINT16_ARRAY: - a = (uint16_t)a; - goto done; - case JS_CLASS_INT32_ARRAY: - done: - ret = JS_NewInt32(ctx, a); - break; - case JS_CLASS_UINT32_ARRAY: - ret = JS_NewUint32(ctx, a); - break; - case JS_CLASS_BIG_INT64_ARRAY: - ret = JS_NewBigInt64(ctx, a); - break; - case JS_CLASS_BIG_UINT64_ARRAY: - ret = JS_NewBigUint64(ctx, a); - break; - default: - abort(); - } - return ret; -} - -static JSValue js_atomics_store(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv) -{ - int size_log2; - void *ptr; - JSValue ret; - JSArrayBuffer *abuf; - - ptr = js_atomics_get_ptr(ctx, &abuf, &size_log2, NULL, - argv[0], argv[1], 0); - if (!ptr) - return JS_EXCEPTION; - if (size_log2 == 3) { - int64_t v64; - ret = JS_ToBigIntFree(ctx, JS_DupValue(ctx, argv[2])); - if (JS_IsException(ret)) - return ret; - if (JS_ToBigInt64(ctx, &v64, ret)) { - JS_FreeValue(ctx, ret); - return JS_EXCEPTION; - } - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - atomic_store((_Atomic(uint64_t) *)ptr, v64); - } else { - uint32_t v; - /* XXX: spec, would be simpler to return the written value */ - ret = JS_ToIntegerFree(ctx, JS_DupValue(ctx, argv[2])); - if (JS_IsException(ret)) - return ret; - if (JS_ToUint32(ctx, &v, ret)) { - JS_FreeValue(ctx, ret); - return JS_EXCEPTION; - } - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - switch(size_log2) { - case 0: - atomic_store((_Atomic(uint8_t) *)ptr, v); - break; - case 1: - atomic_store((_Atomic(uint16_t) *)ptr, v); - break; - case 2: - atomic_store((_Atomic(uint32_t) *)ptr, v); - break; - default: - abort(); - } - } - return ret; -} - -static JSValue js_atomics_isLockFree(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv) -{ - int v, ret; - if (JS_ToInt32Sat(ctx, &v, argv[0])) - return JS_EXCEPTION; - ret = (v == 1 || v == 2 || v == 4 || v == 8); - return JS_NewBool(ctx, ret); -} - -typedef struct JSAtomicsWaiter { - struct list_head link; - BOOL linked; - pthread_cond_t cond; - int32_t *ptr; -} JSAtomicsWaiter; - -static pthread_mutex_t js_atomics_mutex = PTHREAD_MUTEX_INITIALIZER; -static struct list_head js_atomics_waiter_list = - LIST_HEAD_INIT(js_atomics_waiter_list); - -static JSValue js_atomics_wait(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv) -{ - int64_t v; - int32_t v32; - void *ptr; - int64_t timeout; - struct timespec ts; - JSAtomicsWaiter waiter_s, *waiter; - int ret, size_log2, res; - double d; - - ptr = js_atomics_get_ptr(ctx, NULL, &size_log2, NULL, - argv[0], argv[1], 2); - if (!ptr) - return JS_EXCEPTION; - if (size_log2 == 3) { - if (JS_ToBigInt64(ctx, &v, argv[2])) - return JS_EXCEPTION; - } else { - if (JS_ToInt32(ctx, &v32, argv[2])) - return JS_EXCEPTION; - v = v32; - } - if (JS_ToFloat64(ctx, &d, argv[3])) - return JS_EXCEPTION; - /* must use INT64_MAX + 1 because INT64_MAX cannot be exactly represented as a double */ - if (isnan(d) || d >= 0x1p63) - timeout = INT64_MAX; - else if (d < 0) - timeout = 0; - else - timeout = (int64_t)d; - if (!ctx->rt->can_block) - return JS_ThrowTypeError(ctx, "cannot block in this thread"); - - /* XXX: inefficient if large number of waiters, should hash on - 'ptr' value */ - /* XXX: use Linux futexes when available ? */ - pthread_mutex_lock(&js_atomics_mutex); - if (size_log2 == 3) { - res = *(int64_t *)ptr != v; - } else { - res = *(int32_t *)ptr != v; - } - if (res) { - pthread_mutex_unlock(&js_atomics_mutex); - return JS_AtomToString(ctx, JS_ATOM_not_equal); - } - - waiter = &waiter_s; - waiter->ptr = ptr; - pthread_cond_init(&waiter->cond, NULL); - waiter->linked = TRUE; - list_add_tail(&waiter->link, &js_atomics_waiter_list); - - if (timeout == INT64_MAX) { - pthread_cond_wait(&waiter->cond, &js_atomics_mutex); - ret = 0; - } else { - /* XXX: use clock monotonic */ - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += timeout / 1000; - ts.tv_nsec += (timeout % 1000) * 1000000; - if (ts.tv_nsec >= 1000000000) { - ts.tv_nsec -= 1000000000; - ts.tv_sec++; - } - ret = pthread_cond_timedwait(&waiter->cond, &js_atomics_mutex, - &ts); - } - if (waiter->linked) - list_del(&waiter->link); - pthread_mutex_unlock(&js_atomics_mutex); - pthread_cond_destroy(&waiter->cond); - if (ret == ETIMEDOUT) { - return JS_AtomToString(ctx, JS_ATOM_timed_out); - } else { - return JS_AtomToString(ctx, JS_ATOM_ok); - } -} - -static JSValue js_atomics_notify(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv) -{ - struct list_head *el, *el1, waiter_list; - int32_t count, n; - void *ptr; - JSAtomicsWaiter *waiter; - JSArrayBuffer *abuf; - - ptr = js_atomics_get_ptr(ctx, &abuf, NULL, NULL, argv[0], argv[1], 1); - if (!ptr) - return JS_EXCEPTION; - - if (JS_IsUndefined(argv[2])) { - count = INT32_MAX; - } else { - if (JS_ToInt32Clamp(ctx, &count, argv[2], 0, INT32_MAX, 0)) - return JS_EXCEPTION; - } - if (abuf->detached) - return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); - - n = 0; - if (abuf->shared && count > 0) { - pthread_mutex_lock(&js_atomics_mutex); - init_list_head(&waiter_list); - list_for_each_safe(el, el1, &js_atomics_waiter_list) { - waiter = list_entry(el, JSAtomicsWaiter, link); - if (waiter->ptr == ptr) { - list_del(&waiter->link); - waiter->linked = FALSE; - list_add_tail(&waiter->link, &waiter_list); - n++; - if (n >= count) - break; - } - } - list_for_each(el, &waiter_list) { - waiter = list_entry(el, JSAtomicsWaiter, link); - pthread_cond_signal(&waiter->cond); - } - pthread_mutex_unlock(&js_atomics_mutex); - } - return JS_NewInt32(ctx, n); -} - -static const JSCFunctionListEntry js_atomics_funcs[] = { - JS_CFUNC_MAGIC_DEF("add", 3, js_atomics_op, ATOMICS_OP_ADD ), - JS_CFUNC_MAGIC_DEF("and", 3, js_atomics_op, ATOMICS_OP_AND ), - JS_CFUNC_MAGIC_DEF("or", 3, js_atomics_op, ATOMICS_OP_OR ), - JS_CFUNC_MAGIC_DEF("sub", 3, js_atomics_op, ATOMICS_OP_SUB ), - JS_CFUNC_MAGIC_DEF("xor", 3, js_atomics_op, ATOMICS_OP_XOR ), - JS_CFUNC_MAGIC_DEF("exchange", 3, js_atomics_op, ATOMICS_OP_EXCHANGE ), - JS_CFUNC_MAGIC_DEF("compareExchange", 4, js_atomics_op, ATOMICS_OP_COMPARE_EXCHANGE ), - JS_CFUNC_MAGIC_DEF("load", 2, js_atomics_op, ATOMICS_OP_LOAD ), - JS_CFUNC_DEF("store", 3, js_atomics_store ), - JS_CFUNC_DEF("isLockFree", 1, js_atomics_isLockFree ), - JS_CFUNC_DEF("wait", 4, js_atomics_wait ), - JS_CFUNC_DEF("notify", 3, js_atomics_notify ), - JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Atomics", JS_PROP_CONFIGURABLE ), -}; - -static const JSCFunctionListEntry js_atomics_obj[] = { - JS_OBJECT_DEF("Atomics", js_atomics_funcs, countof(js_atomics_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), -}; - -void JS_AddIntrinsicAtomics(JSContext *ctx) -{ - /* add Atomics as autoinit object */ - JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_atomics_obj, countof(js_atomics_obj)); -} - -#endif /* CONFIG_ATOMICS */ - -void JS_AddIntrinsicTypedArrays(JSContext *ctx) -{ - JSValue typed_array_base_proto, typed_array_base_func; - JSValueConst array_buffer_func, shared_array_buffer_func; - int i; - - ctx->class_proto[JS_CLASS_ARRAY_BUFFER] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY_BUFFER], - js_array_buffer_proto_funcs, - countof(js_array_buffer_proto_funcs)); - - array_buffer_func = JS_NewGlobalCConstructorOnly(ctx, "ArrayBuffer", - js_array_buffer_constructor, 1, - ctx->class_proto[JS_CLASS_ARRAY_BUFFER]); - JS_SetPropertyFunctionList(ctx, array_buffer_func, - js_array_buffer_funcs, - countof(js_array_buffer_funcs)); - - ctx->class_proto[JS_CLASS_SHARED_ARRAY_BUFFER] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_SHARED_ARRAY_BUFFER], - js_shared_array_buffer_proto_funcs, - countof(js_shared_array_buffer_proto_funcs)); - - shared_array_buffer_func = JS_NewGlobalCConstructorOnly(ctx, "SharedArrayBuffer", - js_shared_array_buffer_constructor, 1, - ctx->class_proto[JS_CLASS_SHARED_ARRAY_BUFFER]); - JS_SetPropertyFunctionList(ctx, shared_array_buffer_func, - js_shared_array_buffer_funcs, - countof(js_shared_array_buffer_funcs)); - - typed_array_base_proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, typed_array_base_proto, - js_typed_array_base_proto_funcs, - countof(js_typed_array_base_proto_funcs)); - - /* TypedArray.prototype.toString must be the same object as Array.prototype.toString */ - JSValue obj = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_toString); - /* XXX: should use alias method in JSCFunctionListEntry */ //@@@ - JS_DefinePropertyValue(ctx, typed_array_base_proto, JS_ATOM_toString, obj, - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - - typed_array_base_func = JS_NewCFunction2(ctx, js_typed_array_base_constructor, - "TypedArray", 0, JS_CFUNC_constructor_or_func, 0); - JS_SetPropertyFunctionList(ctx, typed_array_base_func, - js_typed_array_base_funcs, - countof(js_typed_array_base_funcs)); - JS_SetConstructor(ctx, typed_array_base_func, typed_array_base_proto); - - /* Used to squelch a -Wcast-function-type warning. */ - JSCFunctionType ft = { .generic_magic = js_typed_array_constructor }; - for(i = JS_CLASS_UINT8C_ARRAY; i < JS_CLASS_UINT8C_ARRAY + JS_TYPED_ARRAY_COUNT; i++) { - JSValue func_obj; - char buf[ATOM_GET_STR_BUF_SIZE]; - const char *name; - - ctx->class_proto[i] = JS_NewObjectProto(ctx, typed_array_base_proto); - JS_DefinePropertyValueStr(ctx, ctx->class_proto[i], - "BYTES_PER_ELEMENT", - JS_NewInt32(ctx, 1 << typed_array_size_log2(i)), - 0); - name = JS_AtomGetStr(ctx, buf, sizeof(buf), - JS_ATOM_Uint8ClampedArray + i - JS_CLASS_UINT8C_ARRAY); - func_obj = JS_NewCFunction3(ctx, ft.generic, - name, 3, JS_CFUNC_constructor_magic, i, - typed_array_base_func); - JS_NewGlobalCConstructor2(ctx, func_obj, name, ctx->class_proto[i]); - JS_DefinePropertyValueStr(ctx, func_obj, - "BYTES_PER_ELEMENT", - JS_NewInt32(ctx, 1 << typed_array_size_log2(i)), - 0); - } - JS_FreeValue(ctx, typed_array_base_proto); - JS_FreeValue(ctx, typed_array_base_func); - - /* DataView */ - ctx->class_proto[JS_CLASS_DATAVIEW] = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_DATAVIEW], - js_dataview_proto_funcs, - countof(js_dataview_proto_funcs)); - JS_NewGlobalCConstructorOnly(ctx, "DataView", - js_dataview_constructor, 1, - ctx->class_proto[JS_CLASS_DATAVIEW]); - /* Atomics */ -#ifdef CONFIG_ATOMICS - JS_AddIntrinsicAtomics(ctx); -#endif -} - /* WeakRef */ typedef struct JSWeakRefData { diff --git a/source/quickjs.h b/source/quickjs.h index 46ee8895..820436aa 100644 --- a/source/quickjs.h +++ b/source/quickjs.h @@ -400,7 +400,7 @@ void JS_AddIntrinsicRegExp(JSContext *ctx); void JS_AddIntrinsicJSON(JSContext *ctx); void JS_AddIntrinsicProxy(JSContext *ctx); void JS_AddIntrinsicMapSet(JSContext *ctx); -void JS_AddIntrinsicTypedArrays(JSContext *ctx); +void JS_AddIntrinsicWeakRef(JSContext *ctx); JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); @@ -853,44 +853,6 @@ JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len, JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, JSValueConst replacer, JSValueConst space0); -typedef void JSFreeArrayBufferDataFunc(JSRuntime *rt, void *opaque, void *ptr); -JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, - JSFreeArrayBufferDataFunc *free_func, void *opaque, - JS_BOOL is_shared); -JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len); -void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj); -uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj); - -typedef enum JSTypedArrayEnum { - JS_TYPED_ARRAY_UINT8C = 0, - JS_TYPED_ARRAY_INT8, - JS_TYPED_ARRAY_UINT8, - JS_TYPED_ARRAY_INT16, - JS_TYPED_ARRAY_UINT16, - JS_TYPED_ARRAY_INT32, - JS_TYPED_ARRAY_UINT32, - JS_TYPED_ARRAY_BIG_INT64, - JS_TYPED_ARRAY_BIG_UINT64, - JS_TYPED_ARRAY_FLOAT16, - JS_TYPED_ARRAY_FLOAT32, - JS_TYPED_ARRAY_FLOAT64, -} JSTypedArrayEnum; - -JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv, - JSTypedArrayEnum array_type); -JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, - size_t *pbyte_offset, - size_t *pbyte_length, - size_t *pbytes_per_element); -typedef struct { - void *(*sab_alloc)(void *opaque, size_t size); - void (*sab_free)(void *opaque, void *ptr); - void (*sab_dup)(void *opaque, void *ptr); - void *sab_opaque; -} JSSharedArrayBufferFunctions; -void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, - const JSSharedArrayBufferFunctions *sf); - typedef enum JSPromiseStateEnum { JS_PROMISE_PENDING, JS_PROMISE_FULFILLED, @@ -910,8 +872,6 @@ void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTrac /* return != 0 if the JS code needs to be interrupted */ typedef int JSInterruptHandler(JSRuntime *rt, void *opaque); void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque); -/* if can_block is TRUE, Atomics.wait() can be used */ -void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block); /* select which debug info is stripped from the compiled code */ #define JS_STRIP_SOURCE (1 << 0) /* strip source code */ #define JS_STRIP_DEBUG (1 << 1) /* strip all debug info including source code */