mirror of
https://github.com/bellard/quickjs.git
synced 2025-09-27 13:48:45 +03:00
added Iterator.prototype.toArray and Iterator.from (bnoordhuis)
This commit is contained in:
parent
982b7aa14f
commit
e924173c0f
@ -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(IteratorWrap, "Iterator Wrap")
|
||||||
DEF(Map_Iterator, "Map Iterator")
|
DEF(Map_Iterator, "Map Iterator")
|
||||||
DEF(Set_Iterator, "Set Iterator")
|
DEF(Set_Iterator, "Set Iterator")
|
||||||
DEF(Array_Iterator, "Array Iterator")
|
DEF(Array_Iterator, "Array Iterator")
|
||||||
|
158
quickjs.c
158
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_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 */
|
||||||
JS_CLASS_ARRAY_ITERATOR, /* u.array_iterator_data */
|
JS_CLASS_ARRAY_ITERATOR, /* u.array_iterator_data */
|
||||||
@ -950,6 +951,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 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 */
|
||||||
struct JSPromiseFunctionData *promise_function_data; /* JS_CLASS_PROMISE_RESOLVE_FUNCTION, JS_CLASS_PROMISE_REJECT_FUNCTION */
|
struct JSPromiseFunctionData *promise_function_data; /* JS_CLASS_PROMISE_RESOLVE_FUNCTION, JS_CLASS_PROMISE_REJECT_FUNCTION */
|
||||||
@ -1134,6 +1136,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_wrap_finalizer(JSRuntime *rt, JSValue val);
|
||||||
|
static void js_iterator_wrap_mark(JSRuntime *rt, JSValueConst val,
|
||||||
|
JS_MarkFunc *mark_func);
|
||||||
static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val);
|
static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val);
|
||||||
static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val,
|
static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val,
|
||||||
JS_MarkFunc *mark_func);
|
JS_MarkFunc *mark_func);
|
||||||
@ -1542,6 +1547,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_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 */
|
||||||
{ JS_ATOM_Array_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_ARRAY_ITERATOR */
|
{ JS_ATOM_Array_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_ARRAY_ITERATOR */
|
||||||
@ -42164,6 +42170,65 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* IteratorWrap */
|
||||||
|
|
||||||
|
typedef struct JSIteratorWrapData {
|
||||||
|
JSValue wrapped_iter;
|
||||||
|
JSValue wrapped_next;
|
||||||
|
} JSIteratorWrapData;
|
||||||
|
|
||||||
|
static void js_iterator_wrap_finalizer(JSRuntime *rt, JSValue val)
|
||||||
|
{
|
||||||
|
JSObject *p = JS_VALUE_GET_OBJ(val);
|
||||||
|
JSIteratorWrapData *it = p->u.iterator_wrap_data;
|
||||||
|
if (it) {
|
||||||
|
JS_FreeValueRT(rt, it->wrapped_iter);
|
||||||
|
JS_FreeValueRT(rt, it->wrapped_next);
|
||||||
|
js_free_rt(rt, it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void js_iterator_wrap_mark(JSRuntime *rt, JSValueConst val,
|
||||||
|
JS_MarkFunc *mark_func)
|
||||||
|
{
|
||||||
|
JSObject *p = JS_VALUE_GET_OBJ(val);
|
||||||
|
JSIteratorWrapData *it = p->u.iterator_wrap_data;
|
||||||
|
if (it) {
|
||||||
|
JS_MarkValue(rt, it->wrapped_iter, mark_func);
|
||||||
|
JS_MarkValue(rt, it->wrapped_next, mark_func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_iterator_wrap_next(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv,
|
||||||
|
int *pdone, int magic)
|
||||||
|
{
|
||||||
|
JSIteratorWrapData *it;
|
||||||
|
JSValue method, ret;
|
||||||
|
it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_WRAP);
|
||||||
|
if (!it)
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
if (magic == GEN_MAGIC_NEXT)
|
||||||
|
return JS_IteratorNext(ctx, it->wrapped_iter, it->wrapped_next, argc, argv, pdone);
|
||||||
|
method = JS_GetProperty(ctx, it->wrapped_iter, JS_ATOM_return);
|
||||||
|
if (JS_IsException(method))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
if (JS_IsNull(method) || JS_IsUndefined(method)) {
|
||||||
|
*pdone = TRUE;
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
ret = JS_IteratorNext2(ctx, it->wrapped_iter, method, argc, argv, pdone);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_iterator_wrap_proto_funcs[] = {
|
||||||
|
JS_ITERATOR_NEXT_DEF("next", 0, js_iterator_wrap_next, GEN_MAGIC_NEXT ),
|
||||||
|
JS_ITERATOR_NEXT_DEF("return", 0, js_iterator_wrap_next, GEN_MAGIC_RETURN ),
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Iterator */
|
||||||
|
|
||||||
static JSValue js_iterator_constructor(JSContext *ctx, JSValueConst new_target,
|
static JSValue js_iterator_constructor(JSContext *ctx, JSValueConst new_target,
|
||||||
int argc, JSValueConst *argv)
|
int argc, JSValueConst *argv)
|
||||||
{
|
{
|
||||||
@ -42173,6 +42238,92 @@ static JSValue js_iterator_constructor(JSContext *ctx, JSValueConst new_target,
|
|||||||
return js_create_from_ctor(ctx, new_target, JS_CLASS_ITERATOR);
|
return js_create_from_ctor(ctx, new_target, JS_CLASS_ITERATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSValue js_iterator_from(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
JSValue method, iter;
|
||||||
|
JSIteratorWrapData *it;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
JSValueConst obj = argv[0];
|
||||||
|
if (JS_IsString(obj)) {
|
||||||
|
method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator);
|
||||||
|
if (JS_IsException(method))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
return JS_CallFree(ctx, method, obj, 0, NULL);
|
||||||
|
}
|
||||||
|
if (!JS_IsObject(obj))
|
||||||
|
return JS_ThrowTypeError(ctx, "Iterator.from called on non-object");
|
||||||
|
ret = JS_OrdinaryIsInstanceOf(ctx, obj, ctx->iterator_ctor);
|
||||||
|
if (ret < 0)
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
if (ret)
|
||||||
|
return JS_DupValue(ctx, obj);
|
||||||
|
method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator);
|
||||||
|
if (JS_IsException(method))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
if (JS_IsNull(method) || JS_IsUndefined(method)) {
|
||||||
|
method = JS_GetProperty(ctx, obj, JS_ATOM_next);
|
||||||
|
if (JS_IsException(method))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
iter = JS_NewObjectClass(ctx, JS_CLASS_ITERATOR_WRAP);
|
||||||
|
if (JS_IsException(iter))
|
||||||
|
goto fail;
|
||||||
|
it = js_malloc(ctx, sizeof(*it));
|
||||||
|
if (!it)
|
||||||
|
goto fail;
|
||||||
|
it->wrapped_iter = JS_DupValue(ctx, obj);
|
||||||
|
it->wrapped_next = method;
|
||||||
|
JS_SetOpaque(iter, it);
|
||||||
|
} else {
|
||||||
|
iter = JS_GetIterator2(ctx, obj, method);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
if (JS_IsException(iter))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
return iter;
|
||||||
|
fail:
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
JS_FreeValue(ctx, iter);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_iterator_proto_toArray(JSContext *ctx, JSValueConst this_val,
|
||||||
|
int argc, JSValueConst *argv)
|
||||||
|
{
|
||||||
|
JSValue item, method, result;
|
||||||
|
int64_t idx;
|
||||||
|
int done;
|
||||||
|
|
||||||
|
result = JS_UNDEFINED;
|
||||||
|
if (!JS_IsObject(this_val))
|
||||||
|
return JS_ThrowTypeErrorNotAnObject(ctx);
|
||||||
|
method = JS_GetProperty(ctx, this_val, JS_ATOM_next);
|
||||||
|
if (JS_IsException(method))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
result = JS_NewArray(ctx);
|
||||||
|
if (JS_IsException(result))
|
||||||
|
goto exception;
|
||||||
|
for (idx = 0; /*empty*/; idx++) {
|
||||||
|
item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
|
||||||
|
if (JS_IsException(item))
|
||||||
|
goto exception;
|
||||||
|
if (done)
|
||||||
|
break;
|
||||||
|
if (JS_DefinePropertyValueInt64(ctx, result, idx, item,
|
||||||
|
JS_PROP_C_W_E | JS_PROP_THROW) < 0)
|
||||||
|
goto exception;
|
||||||
|
}
|
||||||
|
if (JS_SetProperty(ctx, result, JS_ATOM_length, JS_NewUint32(ctx, idx)) < 0)
|
||||||
|
goto exception;
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
return result;
|
||||||
|
exception:
|
||||||
|
JS_FreeValue(ctx, result);
|
||||||
|
JS_FreeValue(ctx, method);
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
static JSValue js_iterator_proto_iterator(JSContext *ctx, JSValueConst this_val,
|
static JSValue js_iterator_proto_iterator(JSContext *ctx, JSValueConst this_val,
|
||||||
int argc, JSValueConst *argv)
|
int argc, JSValueConst *argv)
|
||||||
{
|
{
|
||||||
@ -42180,9 +42331,11 @@ static JSValue js_iterator_proto_iterator(JSContext *ctx, JSValueConst this_val,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_iterator_funcs[] = {
|
static const JSCFunctionListEntry js_iterator_funcs[] = {
|
||||||
|
JS_CFUNC_DEF("from", 1, js_iterator_from ),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_iterator_proto_funcs[] = {
|
static const JSCFunctionListEntry js_iterator_proto_funcs[] = {
|
||||||
|
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 ),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -53120,6 +53273,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_WRAP] = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ITERATOR]);
|
||||||
|
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ITERATOR_WRAP],
|
||||||
|
js_iterator_wrap_proto_funcs,
|
||||||
|
countof(js_iterator_wrap_proto_funcs));
|
||||||
|
|
||||||
/* Array */
|
/* Array */
|
||||||
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY],
|
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY],
|
||||||
js_array_proto_funcs,
|
js_array_proto_funcs,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user