mirror of
https://github.com/bellard/quickjs.git
synced 2025-09-27 05:38:45 +03:00
added Iterator.prototype.[drop,filter,flatMap,map,take,every,find,forEach,some,reduce,[Symbol.toStringTag]] (saghul)
This commit is contained in:
parent
e924173c0f
commit
b2ed2e91f5
@ -231,6 +231,7 @@ DEF(Set, "Set") /* Map + 1 */
|
|||||||
DEF(WeakMap, "WeakMap") /* Map + 2 */
|
DEF(WeakMap, "WeakMap") /* Map + 2 */
|
||||||
DEF(WeakSet, "WeakSet") /* Map + 3 */
|
DEF(WeakSet, "WeakSet") /* Map + 3 */
|
||||||
DEF(Iterator, "Iterator")
|
DEF(Iterator, "Iterator")
|
||||||
|
DEF(IteratorHelper, "Iterator Helper")
|
||||||
DEF(IteratorWrap, "Iterator Wrap")
|
DEF(IteratorWrap, "Iterator Wrap")
|
||||||
DEF(Map_Iterator, "Map Iterator")
|
DEF(Map_Iterator, "Map Iterator")
|
||||||
DEF(Set_Iterator, "Set Iterator")
|
DEF(Set_Iterator, "Set Iterator")
|
||||||
|
668
quickjs.c
668
quickjs.c
@ -158,6 +158,7 @@ enum {
|
|||||||
JS_CLASS_WEAKMAP, /* u.map_state */
|
JS_CLASS_WEAKMAP, /* u.map_state */
|
||||||
JS_CLASS_WEAKSET, /* u.map_state */
|
JS_CLASS_WEAKSET, /* u.map_state */
|
||||||
JS_CLASS_ITERATOR, /* u.map_iterator_data */
|
JS_CLASS_ITERATOR, /* u.map_iterator_data */
|
||||||
|
JS_CLASS_ITERATOR_HELPER, /* u.iterator_helper_data */
|
||||||
JS_CLASS_ITERATOR_WRAP, /* u.iterator_wrap_data */
|
JS_CLASS_ITERATOR_WRAP, /* u.iterator_wrap_data */
|
||||||
JS_CLASS_MAP_ITERATOR, /* u.map_iterator_data */
|
JS_CLASS_MAP_ITERATOR, /* u.map_iterator_data */
|
||||||
JS_CLASS_SET_ITERATOR, /* u.map_iterator_data */
|
JS_CLASS_SET_ITERATOR, /* u.map_iterator_data */
|
||||||
@ -951,6 +952,7 @@ struct JSObject {
|
|||||||
struct JSArrayIteratorData *array_iterator_data; /* JS_CLASS_ARRAY_ITERATOR, JS_CLASS_STRING_ITERATOR */
|
struct JSArrayIteratorData *array_iterator_data; /* JS_CLASS_ARRAY_ITERATOR, JS_CLASS_STRING_ITERATOR */
|
||||||
struct JSRegExpStringIteratorData *regexp_string_iterator_data; /* JS_CLASS_REGEXP_STRING_ITERATOR */
|
struct JSRegExpStringIteratorData *regexp_string_iterator_data; /* JS_CLASS_REGEXP_STRING_ITERATOR */
|
||||||
struct JSGeneratorData *generator_data; /* JS_CLASS_GENERATOR */
|
struct JSGeneratorData *generator_data; /* JS_CLASS_GENERATOR */
|
||||||
|
struct JSIteratorHelperData *iterator_helper_data; /* JS_CLASS_ITERATOR_HELPER */
|
||||||
struct JSIteratorWrapData *iterator_wrap_data; /* JS_CLASS_ITERATOR_WRAP */
|
struct JSIteratorWrapData *iterator_wrap_data; /* JS_CLASS_ITERATOR_WRAP */
|
||||||
struct JSProxyData *proxy_data; /* JS_CLASS_PROXY */
|
struct JSProxyData *proxy_data; /* JS_CLASS_PROXY */
|
||||||
struct JSPromiseData *promise_data; /* JS_CLASS_PROMISE */
|
struct JSPromiseData *promise_data; /* JS_CLASS_PROMISE */
|
||||||
@ -1136,6 +1138,9 @@ static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val,
|
|||||||
static void js_array_iterator_finalizer(JSRuntime *rt, JSValue val);
|
static void js_array_iterator_finalizer(JSRuntime *rt, JSValue val);
|
||||||
static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val,
|
static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val,
|
||||||
JS_MarkFunc *mark_func);
|
JS_MarkFunc *mark_func);
|
||||||
|
static void js_iterator_helper_finalizer(JSRuntime *rt, JSValue val);
|
||||||
|
static void js_iterator_helper_mark(JSRuntime *rt, JSValueConst val,
|
||||||
|
JS_MarkFunc *mark_func);
|
||||||
static void js_iterator_wrap_finalizer(JSRuntime *rt, JSValue val);
|
static void js_iterator_wrap_finalizer(JSRuntime *rt, JSValue val);
|
||||||
static void js_iterator_wrap_mark(JSRuntime *rt, JSValueConst val,
|
static void js_iterator_wrap_mark(JSRuntime *rt, JSValueConst val,
|
||||||
JS_MarkFunc *mark_func);
|
JS_MarkFunc *mark_func);
|
||||||
@ -1547,6 +1552,7 @@ static JSClassShortDef const js_std_class_def[] = {
|
|||||||
{ JS_ATOM_WeakMap, js_map_finalizer, js_map_mark }, /* JS_CLASS_WEAKMAP */
|
{ JS_ATOM_WeakMap, js_map_finalizer, js_map_mark }, /* JS_CLASS_WEAKMAP */
|
||||||
{ JS_ATOM_WeakSet, js_map_finalizer, js_map_mark }, /* JS_CLASS_WEAKSET */
|
{ JS_ATOM_WeakSet, js_map_finalizer, js_map_mark }, /* JS_CLASS_WEAKSET */
|
||||||
{ JS_ATOM_Iterator, NULL, NULL }, /* JS_CLASS_ITERATOR */
|
{ JS_ATOM_Iterator, NULL, NULL }, /* JS_CLASS_ITERATOR */
|
||||||
|
{ JS_ATOM_IteratorHelper, js_iterator_helper_finalizer, js_iterator_helper_mark }, /* JS_CLASS_ITERATOR_HELPER */
|
||||||
{ JS_ATOM_IteratorWrap, js_iterator_wrap_finalizer, js_iterator_wrap_mark }, /* JS_CLASS_ITERATOR_WRAP */
|
{ JS_ATOM_IteratorWrap, js_iterator_wrap_finalizer, js_iterator_wrap_mark }, /* JS_CLASS_ITERATOR_WRAP */
|
||||||
{ JS_ATOM_Map_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_MAP_ITERATOR */
|
{ JS_ATOM_Map_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_MAP_ITERATOR */
|
||||||
{ JS_ATOM_Set_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_SET_ITERATOR */
|
{ JS_ATOM_Set_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_SET_ITERATOR */
|
||||||
@ -42288,6 +42294,338 @@ fail:
|
|||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum JSIteratorHelperKindEnum {
|
||||||
|
JS_ITERATOR_HELPER_KIND_DROP,
|
||||||
|
JS_ITERATOR_HELPER_KIND_EVERY,
|
||||||
|
JS_ITERATOR_HELPER_KIND_FILTER,
|
||||||
|
JS_ITERATOR_HELPER_KIND_FIND,
|
||||||
|
JS_ITERATOR_HELPER_KIND_FLAT_MAP,
|
||||||
|
JS_ITERATOR_HELPER_KIND_FOR_EACH,
|
||||||
|
JS_ITERATOR_HELPER_KIND_MAP,
|
||||||
|
JS_ITERATOR_HELPER_KIND_SOME,
|
||||||
|
JS_ITERATOR_HELPER_KIND_TAKE,
|
||||||
|
} JSIteratorHelperKindEnum;
|
||||||
|
|
||||||
|
typedef struct JSIteratorHelperData {
|
||||||
|
JSValue obj;
|
||||||
|
JSValue next;
|
||||||
|
JSValue func; // predicate (filter) or mapper (flatMap, map)
|
||||||
|
JSValue inner; // innerValue (flatMap)
|
||||||
|
int64_t count; // limit (drop, take) or counter (filter, map, flatMap)
|
||||||
|
JSIteratorHelperKindEnum kind : 8;
|
||||||
|
uint8_t executing : 1;
|
||||||
|
uint8_t done : 1;
|
||||||
|
} JSIteratorHelperData;
|
||||||
|
|
||||||
|
static JSValue js_create_iterator_helper(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv, int magic)
|
||||||
|
{
|
||||||
|
JSValueConst func;
|
||||||
|
JSValue obj, method;
|
||||||
|
int64_t count;
|
||||||
|
JSIteratorHelperData *it;
|
||||||
|
|
||||||
|
if (!JS_IsObject(this_val))
|
||||||
|
return JS_ThrowTypeErrorNotAnObject(ctx);
|
||||||
|
func = JS_UNDEFINED;
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
switch(magic) {
|
||||||
|
case JS_ITERATOR_HELPER_KIND_DROP:
|
||||||
|
case JS_ITERATOR_HELPER_KIND_TAKE:
|
||||||
|
{
|
||||||
|
JSValue v;
|
||||||
|
double dlimit;
|
||||||
|
v = JS_ToNumber(ctx, argv[0]);
|
||||||
|
if (JS_IsException(v))
|
||||||
|
goto fail;
|
||||||
|
// Check for Infinity.
|
||||||
|
if (JS_ToFloat64(ctx, &dlimit, v)) {
|
||||||
|
JS_FreeValue(ctx, v);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (isnan(dlimit)) {
|
||||||
|
JS_FreeValue(ctx, v);
|
||||||
|
goto range_error;
|
||||||
|
}
|
||||||
|
if (!isfinite(dlimit)) {
|
||||||
|
JS_FreeValue(ctx, v);
|
||||||
|
if (dlimit < 0)
|
||||||
|
goto range_error;
|
||||||
|
else
|
||||||
|
count = MAX_SAFE_INTEGER;
|
||||||
|
} else {
|
||||||
|
v = JS_ToIntegerFree(ctx, v);
|
||||||
|
if (JS_IsException(v))
|
||||||
|
goto fail;
|
||||||
|
if (JS_ToInt64Free(ctx, &count, v))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (count < 0)
|
||||||
|
goto range_error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JS_ITERATOR_HELPER_KIND_FILTER:
|
||||||
|
case JS_ITERATOR_HELPER_KIND_FLAT_MAP:
|
||||||
|
case JS_ITERATOR_HELPER_KIND_MAP:
|
||||||
|
{
|
||||||
|
func = argv[0];
|
||||||
|
if (check_function(ctx, func))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
method = JS_GetProperty(ctx, this_val, JS_ATOM_next);
|
||||||
|
if (JS_IsException(method))
|
||||||
|
goto fail;
|
||||||
|
obj = JS_NewObjectClass(ctx, JS_CLASS_ITERATOR_HELPER);
|
||||||
|
if (JS_IsException(obj)) {
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
it = js_malloc(ctx, sizeof(*it));
|
||||||
|
if (!it) {
|
||||||
|
JS_FreeValue(ctx, obj);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
it->kind = magic;
|
||||||
|
it->obj = JS_DupValue(ctx, this_val);
|
||||||
|
it->func = JS_DupValue(ctx, func);
|
||||||
|
it->next = method;
|
||||||
|
it->inner = JS_UNDEFINED;
|
||||||
|
it->count = count;
|
||||||
|
it->executing = 0;
|
||||||
|
it->done = 0;
|
||||||
|
JS_SetOpaque(obj, it);
|
||||||
|
return obj;
|
||||||
|
range_error:
|
||||||
|
JS_ThrowRangeError(ctx, "must be positive");
|
||||||
|
fail:
|
||||||
|
JS_IteratorClose(ctx, this_val, TRUE);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv, int magic)
|
||||||
|
{
|
||||||
|
JSValue item, method, ret, func, index_val, r;
|
||||||
|
JSValueConst args[2];
|
||||||
|
int64_t idx;
|
||||||
|
int done;
|
||||||
|
|
||||||
|
if (!JS_IsObject(this_val))
|
||||||
|
return JS_ThrowTypeErrorNotAnObject(ctx);
|
||||||
|
func = JS_UNDEFINED;
|
||||||
|
method = JS_UNDEFINED;
|
||||||
|
if (check_function(ctx, argv[0]))
|
||||||
|
goto fail;
|
||||||
|
func = JS_DupValue(ctx, argv[0]);
|
||||||
|
method = JS_GetProperty(ctx, this_val, JS_ATOM_next);
|
||||||
|
if (JS_IsException(method))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
r = JS_UNDEFINED;
|
||||||
|
|
||||||
|
switch(magic) {
|
||||||
|
case JS_ITERATOR_HELPER_KIND_EVERY:
|
||||||
|
{
|
||||||
|
r = JS_TRUE;
|
||||||
|
for (idx = 0; /*empty*/; idx++) {
|
||||||
|
item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
|
||||||
|
if (JS_IsException(item))
|
||||||
|
goto fail;
|
||||||
|
if (done)
|
||||||
|
break;
|
||||||
|
index_val = JS_NewInt64(ctx, idx);
|
||||||
|
args[0] = item;
|
||||||
|
args[1] = index_val;
|
||||||
|
ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args);
|
||||||
|
JS_FreeValue(ctx, item);
|
||||||
|
JS_FreeValue(ctx, index_val);
|
||||||
|
if (JS_IsException(ret))
|
||||||
|
goto fail;
|
||||||
|
if (!JS_ToBoolFree(ctx, ret)) {
|
||||||
|
if (JS_IteratorClose(ctx, this_val, FALSE) < 0)
|
||||||
|
r = JS_EXCEPTION;
|
||||||
|
else
|
||||||
|
r = JS_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index_val = JS_UNDEFINED;
|
||||||
|
ret = JS_UNDEFINED;
|
||||||
|
item = JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JS_ITERATOR_HELPER_KIND_FIND:
|
||||||
|
{
|
||||||
|
for (idx = 0; /*empty*/; idx++) {
|
||||||
|
item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
|
||||||
|
if (JS_IsException(item))
|
||||||
|
goto fail;
|
||||||
|
if (done)
|
||||||
|
break;
|
||||||
|
index_val = JS_NewInt64(ctx, idx);
|
||||||
|
args[0] = item;
|
||||||
|
args[1] = index_val;
|
||||||
|
ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args);
|
||||||
|
JS_FreeValue(ctx, index_val);
|
||||||
|
if (JS_IsException(ret)) {
|
||||||
|
JS_FreeValue(ctx, item);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (JS_ToBoolFree(ctx, ret)) {
|
||||||
|
if (JS_IteratorClose(ctx, this_val, FALSE) < 0) {
|
||||||
|
JS_FreeValue(ctx, item);
|
||||||
|
r = JS_EXCEPTION;
|
||||||
|
} else {
|
||||||
|
r = item;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index_val = JS_UNDEFINED;
|
||||||
|
ret = JS_UNDEFINED;
|
||||||
|
item = JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JS_ITERATOR_HELPER_KIND_FOR_EACH:
|
||||||
|
{
|
||||||
|
for (idx = 0; /*empty*/; idx++) {
|
||||||
|
item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
|
||||||
|
if (JS_IsException(item))
|
||||||
|
goto fail;
|
||||||
|
if (done)
|
||||||
|
break;
|
||||||
|
index_val = JS_NewInt64(ctx, idx);
|
||||||
|
args[0] = item;
|
||||||
|
args[1] = index_val;
|
||||||
|
ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args);
|
||||||
|
JS_FreeValue(ctx, item);
|
||||||
|
JS_FreeValue(ctx, index_val);
|
||||||
|
if (JS_IsException(ret))
|
||||||
|
goto fail;
|
||||||
|
JS_FreeValue(ctx, ret);
|
||||||
|
index_val = JS_UNDEFINED;
|
||||||
|
ret = JS_UNDEFINED;
|
||||||
|
item = JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JS_ITERATOR_HELPER_KIND_SOME:
|
||||||
|
{
|
||||||
|
r = JS_FALSE;
|
||||||
|
for (idx = 0; /*empty*/; idx++) {
|
||||||
|
item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
|
||||||
|
if (JS_IsException(item))
|
||||||
|
goto fail;
|
||||||
|
if (done)
|
||||||
|
break;
|
||||||
|
index_val = JS_NewInt64(ctx, idx);
|
||||||
|
args[0] = item;
|
||||||
|
args[1] = index_val;
|
||||||
|
ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args);
|
||||||
|
JS_FreeValue(ctx, item);
|
||||||
|
JS_FreeValue(ctx, index_val);
|
||||||
|
if (JS_IsException(ret))
|
||||||
|
goto fail;
|
||||||
|
if (JS_ToBoolFree(ctx, ret)) {
|
||||||
|
if (JS_IteratorClose(ctx, this_val, FALSE) < 0)
|
||||||
|
r = JS_EXCEPTION;
|
||||||
|
else
|
||||||
|
r = JS_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index_val = JS_UNDEFINED;
|
||||||
|
ret = JS_UNDEFINED;
|
||||||
|
item = JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_FreeValue(ctx, func);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
return r;
|
||||||
|
fail:
|
||||||
|
JS_IteratorClose(ctx, this_val, TRUE);
|
||||||
|
JS_FreeValue(ctx, func);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
JSValue item, method, ret, func, index_val, acc;
|
||||||
|
JSValueConst args[3];
|
||||||
|
int64_t idx;
|
||||||
|
int done;
|
||||||
|
|
||||||
|
if (!JS_IsObject(this_val))
|
||||||
|
return JS_ThrowTypeErrorNotAnObject(ctx);
|
||||||
|
acc = JS_UNDEFINED;
|
||||||
|
func = JS_UNDEFINED;
|
||||||
|
method = JS_UNDEFINED;
|
||||||
|
if (check_function(ctx, argv[0]))
|
||||||
|
goto exception;
|
||||||
|
func = JS_DupValue(ctx, argv[0]);
|
||||||
|
method = JS_GetProperty(ctx, this_val, JS_ATOM_next);
|
||||||
|
if (JS_IsException(method))
|
||||||
|
goto exception;
|
||||||
|
if (argc > 1) {
|
||||||
|
acc = JS_DupValue(ctx, argv[1]);
|
||||||
|
idx = 0;
|
||||||
|
} else {
|
||||||
|
acc = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
|
||||||
|
if (JS_IsException(acc))
|
||||||
|
goto exception;
|
||||||
|
if (done) {
|
||||||
|
JS_ThrowTypeError(ctx, "empty iterator");
|
||||||
|
goto exception;
|
||||||
|
}
|
||||||
|
idx = 1;
|
||||||
|
}
|
||||||
|
for (/* empty */; /*empty*/; idx++) {
|
||||||
|
item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
|
||||||
|
if (JS_IsException(item))
|
||||||
|
goto exception;
|
||||||
|
if (done)
|
||||||
|
break;
|
||||||
|
index_val = JS_NewInt64(ctx, idx);
|
||||||
|
args[0] = acc;
|
||||||
|
args[1] = item;
|
||||||
|
args[2] = index_val;
|
||||||
|
ret = JS_Call(ctx, func, JS_UNDEFINED, countof(args), args);
|
||||||
|
JS_FreeValue(ctx, item);
|
||||||
|
JS_FreeValue(ctx, index_val);
|
||||||
|
if (JS_IsException(ret))
|
||||||
|
goto exception;
|
||||||
|
JS_FreeValue(ctx, acc);
|
||||||
|
acc = ret;
|
||||||
|
index_val = JS_UNDEFINED;
|
||||||
|
ret = JS_UNDEFINED;
|
||||||
|
item = JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
JS_FreeValue(ctx, func);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
return acc;
|
||||||
|
exception:
|
||||||
|
JS_IteratorClose(ctx, this_val, TRUE);
|
||||||
|
JS_FreeValue(ctx, acc);
|
||||||
|
JS_FreeValue(ctx, func);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
static JSValue js_iterator_proto_toArray(JSContext *ctx, JSValueConst this_val,
|
static JSValue js_iterator_proto_toArray(JSContext *ctx, JSValueConst this_val,
|
||||||
int argc, JSValueConst *argv)
|
int argc, JSValueConst *argv)
|
||||||
{
|
{
|
||||||
@ -42329,14 +42667,337 @@ static JSValue js_iterator_proto_iterator(JSContext *ctx, JSValueConst this_val,
|
|||||||
{
|
{
|
||||||
return JS_DupValue(ctx, this_val);
|
return JS_DupValue(ctx, this_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSValue js_iterator_proto_get_toStringTag(JSContext *ctx, JSValueConst this_val)
|
||||||
|
{
|
||||||
|
return JS_AtomToString(ctx, JS_ATOM_Iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_iterator_proto_set_toStringTag(JSContext *ctx, JSValueConst this_val, JSValueConst val)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (!JS_IsObject(this_val))
|
||||||
|
return JS_ThrowTypeErrorNotAnObject(ctx);
|
||||||
|
if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_ITERATOR]))
|
||||||
|
return JS_ThrowTypeError(ctx, "Cannot assign to read only property");
|
||||||
|
res = JS_GetOwnProperty(ctx, NULL, this_val, JS_ATOM_Symbol_toStringTag);
|
||||||
|
if (res < 0)
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
if (res) {
|
||||||
|
if (JS_SetProperty(ctx, this_val, JS_ATOM_Symbol_toStringTag, JS_DupValue(ctx, val)) < 0)
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
} else {
|
||||||
|
if (JS_DefinePropertyValue(ctx, this_val, JS_ATOM_Symbol_toStringTag, JS_DupValue(ctx, val), JS_PROP_C_W_E) < 0)
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterator Helper */
|
||||||
|
|
||||||
|
static void js_iterator_helper_finalizer(JSRuntime *rt, JSValue val)
|
||||||
|
{
|
||||||
|
JSObject *p = JS_VALUE_GET_OBJ(val);
|
||||||
|
JSIteratorHelperData *it = p->u.iterator_helper_data;
|
||||||
|
if (it) {
|
||||||
|
JS_FreeValueRT(rt, it->obj);
|
||||||
|
JS_FreeValueRT(rt, it->func);
|
||||||
|
JS_FreeValueRT(rt, it->next);
|
||||||
|
JS_FreeValueRT(rt, it->inner);
|
||||||
|
js_free_rt(rt, it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void js_iterator_helper_mark(JSRuntime *rt, JSValueConst val,
|
||||||
|
JS_MarkFunc *mark_func)
|
||||||
|
{
|
||||||
|
JSObject *p = JS_VALUE_GET_OBJ(val);
|
||||||
|
JSIteratorHelperData *it = p->u.iterator_helper_data;
|
||||||
|
if (it) {
|
||||||
|
JS_MarkValue(rt, it->obj, mark_func);
|
||||||
|
JS_MarkValue(rt, it->func, mark_func);
|
||||||
|
JS_MarkValue(rt, it->next, mark_func);
|
||||||
|
JS_MarkValue(rt, it->inner, mark_func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv,
|
||||||
|
int *pdone, int magic)
|
||||||
|
{
|
||||||
|
JSIteratorHelperData *it;
|
||||||
|
JSValue ret;
|
||||||
|
|
||||||
|
*pdone = FALSE;
|
||||||
|
|
||||||
|
it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_HELPER);
|
||||||
|
if (!it)
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
if (it->executing)
|
||||||
|
return JS_ThrowTypeError(ctx, "cannot invoke a running iterator");
|
||||||
|
if (it->done) {
|
||||||
|
*pdone = TRUE;
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
it->executing = 1;
|
||||||
|
|
||||||
|
switch (it->kind) {
|
||||||
|
case JS_ITERATOR_HELPER_KIND_DROP:
|
||||||
|
{
|
||||||
|
JSValue item, method;
|
||||||
|
if (magic == GEN_MAGIC_NEXT) {
|
||||||
|
method = JS_DupValue(ctx, it->next);
|
||||||
|
} else {
|
||||||
|
method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
|
||||||
|
if (JS_IsException(method))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
while (it->count > 0) {
|
||||||
|
it->count--;
|
||||||
|
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
|
||||||
|
if (JS_IsException(item)) {
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
JS_FreeValue(ctx, item);
|
||||||
|
if (magic == GEN_MAGIC_RETURN)
|
||||||
|
*pdone = TRUE;
|
||||||
|
if (*pdone) {
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
ret = JS_UNDEFINED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
if (JS_IsException(item))
|
||||||
|
goto fail;
|
||||||
|
ret = item;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JS_ITERATOR_HELPER_KIND_FILTER:
|
||||||
|
{
|
||||||
|
JSValue item, method, selected, index_val;
|
||||||
|
JSValueConst args[2];
|
||||||
|
if (magic == GEN_MAGIC_NEXT) {
|
||||||
|
method = JS_DupValue(ctx, it->next);
|
||||||
|
} else {
|
||||||
|
method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
|
||||||
|
if (JS_IsException(method))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
filter_again:
|
||||||
|
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
|
||||||
|
if (JS_IsException(item)) {
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (*pdone || magic == GEN_MAGIC_RETURN) {
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
ret = item;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
index_val = JS_NewInt64(ctx, it->count++);
|
||||||
|
args[0] = item;
|
||||||
|
args[1] = index_val;
|
||||||
|
selected = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args);
|
||||||
|
JS_FreeValue(ctx, index_val);
|
||||||
|
if (JS_IsException(selected)) {
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (JS_ToBoolFree(ctx, selected)) {
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
ret = item;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
goto filter_again;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JS_ITERATOR_HELPER_KIND_FLAT_MAP:
|
||||||
|
{
|
||||||
|
JSValue item, method, index_val, iter;
|
||||||
|
JSValueConst args[2];
|
||||||
|
flat_map_again:
|
||||||
|
if (JS_IsUndefined(it->inner)) {
|
||||||
|
if (magic == GEN_MAGIC_NEXT) {
|
||||||
|
method = JS_DupValue(ctx, it->next);
|
||||||
|
} else {
|
||||||
|
method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
|
||||||
|
if (JS_IsException(method))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
if (JS_IsException(item))
|
||||||
|
goto fail;
|
||||||
|
if (*pdone || magic == GEN_MAGIC_RETURN) {
|
||||||
|
ret = item;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
index_val = JS_NewInt64(ctx, it->count++);
|
||||||
|
args[0] = item;
|
||||||
|
args[1] = index_val;
|
||||||
|
ret = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args);
|
||||||
|
JS_FreeValue(ctx, item);
|
||||||
|
JS_FreeValue(ctx, index_val);
|
||||||
|
if (JS_IsException(ret))
|
||||||
|
goto fail;
|
||||||
|
if (!JS_IsObject(ret)) {
|
||||||
|
JS_FreeValue(ctx, ret);
|
||||||
|
JS_ThrowTypeError(ctx, "not an object");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
method = JS_GetProperty(ctx, ret, JS_ATOM_Symbol_iterator);
|
||||||
|
if (JS_IsException(method)) {
|
||||||
|
JS_FreeValue(ctx, ret);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (JS_IsNull(method) || JS_IsUndefined(method)) {
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
iter = ret;
|
||||||
|
} else {
|
||||||
|
iter = JS_GetIterator2(ctx, ret, method);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
JS_FreeValue(ctx, ret);
|
||||||
|
if (JS_IsException(iter))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
it->inner = iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (magic == GEN_MAGIC_NEXT)
|
||||||
|
method = JS_GetProperty(ctx, it->inner, JS_ATOM_next);
|
||||||
|
else
|
||||||
|
method = JS_GetProperty(ctx, it->inner, JS_ATOM_return);
|
||||||
|
if (JS_IsException(method)) {
|
||||||
|
inner_fail:
|
||||||
|
JS_IteratorClose(ctx, it->inner, FALSE);
|
||||||
|
JS_FreeValue(ctx, it->inner);
|
||||||
|
it->inner = JS_UNDEFINED;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (magic == GEN_MAGIC_RETURN && (JS_IsUndefined(method) || JS_IsNull(method))) {
|
||||||
|
goto inner_end;
|
||||||
|
} else {
|
||||||
|
item = JS_IteratorNext(ctx, it->inner, method, 0, NULL, pdone);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
if (JS_IsException(item))
|
||||||
|
goto inner_fail;
|
||||||
|
}
|
||||||
|
if (*pdone) {
|
||||||
|
inner_end:
|
||||||
|
*pdone = FALSE; // The outer iterator must continue.
|
||||||
|
JS_IteratorClose(ctx, it->inner, FALSE);
|
||||||
|
JS_FreeValue(ctx, it->inner);
|
||||||
|
it->inner = JS_UNDEFINED;
|
||||||
|
goto flat_map_again;
|
||||||
|
}
|
||||||
|
ret = item;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JS_ITERATOR_HELPER_KIND_MAP:
|
||||||
|
{
|
||||||
|
JSValue item, method, index_val;
|
||||||
|
JSValueConst args[2];
|
||||||
|
if (magic == GEN_MAGIC_NEXT) {
|
||||||
|
method = JS_DupValue(ctx, it->next);
|
||||||
|
} else {
|
||||||
|
method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
|
||||||
|
if (JS_IsException(method))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
if (JS_IsException(item))
|
||||||
|
goto fail;
|
||||||
|
if (*pdone || magic == GEN_MAGIC_RETURN) {
|
||||||
|
ret = item;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
index_val = JS_NewInt64(ctx, it->count++);
|
||||||
|
args[0] = item;
|
||||||
|
args[1] = index_val;
|
||||||
|
ret = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args);
|
||||||
|
JS_FreeValue(ctx, index_val);
|
||||||
|
if (JS_IsException(ret))
|
||||||
|
goto fail;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JS_ITERATOR_HELPER_KIND_TAKE:
|
||||||
|
{
|
||||||
|
JSValue item, method;
|
||||||
|
if (it->count > 0) {
|
||||||
|
if (magic == GEN_MAGIC_NEXT) {
|
||||||
|
method = JS_DupValue(ctx, it->next);
|
||||||
|
} else {
|
||||||
|
method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
|
||||||
|
if (JS_IsException(method))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
it->count--;
|
||||||
|
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
if (JS_IsException(item))
|
||||||
|
goto fail;
|
||||||
|
ret = item;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pdone = TRUE;
|
||||||
|
if (JS_IteratorClose(ctx, it->obj, FALSE))
|
||||||
|
ret = JS_EXCEPTION;
|
||||||
|
else
|
||||||
|
ret = JS_UNDEFINED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
it->done = magic == GEN_MAGIC_NEXT ? *pdone : 1;
|
||||||
|
it->executing = 0;
|
||||||
|
return ret;
|
||||||
|
fail:
|
||||||
|
/* close the iterator object, preserving pending exception */
|
||||||
|
JS_IteratorClose(ctx, it->obj, TRUE);
|
||||||
|
ret = JS_EXCEPTION;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_iterator_funcs[] = {
|
static const JSCFunctionListEntry js_iterator_funcs[] = {
|
||||||
JS_CFUNC_DEF("from", 1, js_iterator_from ),
|
JS_CFUNC_DEF("from", 1, js_iterator_from ),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_iterator_proto_funcs[] = {
|
static const JSCFunctionListEntry js_iterator_proto_funcs[] = {
|
||||||
|
JS_CFUNC_MAGIC_DEF("drop", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_DROP ),
|
||||||
|
JS_CFUNC_MAGIC_DEF("filter", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_FILTER ),
|
||||||
|
JS_CFUNC_MAGIC_DEF("flatMap", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_FLAT_MAP ),
|
||||||
|
JS_CFUNC_MAGIC_DEF("map", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_MAP ),
|
||||||
|
JS_CFUNC_MAGIC_DEF("take", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_TAKE ),
|
||||||
|
JS_CFUNC_MAGIC_DEF("every", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_EVERY ),
|
||||||
|
JS_CFUNC_MAGIC_DEF("find", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_FIND),
|
||||||
|
JS_CFUNC_MAGIC_DEF("forEach", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_FOR_EACH ),
|
||||||
|
JS_CFUNC_MAGIC_DEF("some", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_SOME ),
|
||||||
|
JS_CFUNC_DEF("reduce", 1, js_iterator_proto_reduce ),
|
||||||
JS_CFUNC_DEF("toArray", 0, js_iterator_proto_toArray ),
|
JS_CFUNC_DEF("toArray", 0, js_iterator_proto_toArray ),
|
||||||
JS_CFUNC_DEF("[Symbol.iterator]", 0, js_iterator_proto_iterator ),
|
JS_CFUNC_DEF("[Symbol.iterator]", 0, js_iterator_proto_iterator ),
|
||||||
|
JS_CGETSET_DEF("[Symbol.toStringTag]", js_iterator_proto_get_toStringTag, js_iterator_proto_set_toStringTag),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_iterator_helper_proto_funcs[] = {
|
||||||
|
JS_ITERATOR_NEXT_DEF("next", 0, js_iterator_helper_next, GEN_MAGIC_NEXT ),
|
||||||
|
JS_ITERATOR_NEXT_DEF("return", 0, js_iterator_helper_next, GEN_MAGIC_RETURN ),
|
||||||
|
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Iterator Helper", JS_PROP_CONFIGURABLE ),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_array_proto_funcs[] = {
|
static const JSCFunctionListEntry js_array_proto_funcs[] = {
|
||||||
@ -53273,6 +53934,11 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
|
|||||||
js_iterator_funcs,
|
js_iterator_funcs,
|
||||||
countof(js_iterator_funcs));
|
countof(js_iterator_funcs));
|
||||||
|
|
||||||
|
ctx->class_proto[JS_CLASS_ITERATOR_HELPER] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]);
|
||||||
|
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_HELPER],
|
||||||
|
js_iterator_helper_proto_funcs,
|
||||||
|
countof(js_iterator_helper_proto_funcs));
|
||||||
|
|
||||||
ctx->class_proto[JS_CLASS_ITERATOR_WRAP] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]);
|
ctx->class_proto[JS_CLASS_ITERATOR_WRAP] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]);
|
||||||
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_WRAP],
|
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_WRAP],
|
||||||
js_iterator_wrap_proto_funcs,
|
js_iterator_wrap_proto_funcs,
|
||||||
|
@ -140,7 +140,7 @@ Intl.NumberFormat-v3=skip
|
|||||||
Intl.RelativeTimeFormat=skip
|
Intl.RelativeTimeFormat=skip
|
||||||
Intl.Segmenter=skip
|
Intl.Segmenter=skip
|
||||||
IsHTMLDDA
|
IsHTMLDDA
|
||||||
iterator-helpers=skip
|
iterator-helpers
|
||||||
iterator-sequencing=skip
|
iterator-sequencing=skip
|
||||||
json-modules
|
json-modules
|
||||||
json-parse-with-source=skip
|
json-parse-with-source=skip
|
||||||
|
Loading…
x
Reference in New Issue
Block a user