Fix GC leak in handling of JS_IteratorNext() result

When a generator returned (not yielded) a reference-counted value, built-in
functions ignored it, and the value was not freed.

Fixes #273
This commit is contained in:
Dmitry Volyntsev 2024-05-14 16:20:02 -07:00
parent d378a9f3a5
commit cfed2ec28a

View file

@ -15556,7 +15556,7 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
if (JS_IsException(value)) if (JS_IsException(value))
goto exception; goto exception;
if (done) { if (done) {
/* value is JS_UNDEFINED */ JS_FreeValue(ctx, value);
break; break;
} }
if (JS_DefinePropertyValueUint32(ctx, sp[-3], pos++, value, JS_PROP_C_W_E) < 0) if (JS_DefinePropertyValueUint32(ctx, sp[-3], pos++, value, JS_PROP_C_W_E) < 0)
@ -38748,8 +38748,10 @@ static JSValue iterator_to_array(JSContext *ctx, JSValueConst items)
v = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done); v = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);
if (JS_IsException(v)) if (JS_IsException(v))
goto exception_close; goto exception_close;
if (done) if (done) {
JS_FreeValue(ctx, v);
break; break;
}
if (JS_DefinePropertyValueInt64(ctx, r, k, v, if (JS_DefinePropertyValueInt64(ctx, r, k, v,
JS_PROP_C_W_E | JS_PROP_THROW) < 0) JS_PROP_C_W_E | JS_PROP_THROW) < 0)
goto exception_close; goto exception_close;
@ -39039,8 +39041,10 @@ static JSValue js_array_from(JSContext *ctx, JSValueConst this_val,
v = JS_IteratorNext(ctx, stack[0], stack[1], 0, NULL, &done); v = JS_IteratorNext(ctx, stack[0], stack[1], 0, NULL, &done);
if (JS_IsException(v)) if (JS_IsException(v))
goto exception_close; goto exception_close;
if (done) if (done) {
JS_FreeValue(ctx, v);
break; break;
}
if (mapping) { if (mapping) {
args[0] = v; args[0] = v;
args[1] = JS_NewInt32(ctx, k); args[1] = JS_NewInt32(ctx, k);
@ -47506,8 +47510,10 @@ static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val,
v = JS_IteratorNext(ctx, iter, next, 0, NULL, &done); v = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
if (JS_IsException(v)) if (JS_IsException(v))
goto exception; goto exception;
if (done) if (done) {
break; // v is JS_UNDEFINED JS_FreeValue(ctx, v);
break;
}
args[0] = v; args[0] = v;
args[1] = JS_NewInt64(ctx, idx); args[1] = JS_NewInt64(ctx, idx);
@ -48536,8 +48542,10 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done); item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);
if (JS_IsException(item)) if (JS_IsException(item))
goto fail_reject; goto fail_reject;
if (done) if (done) {
JS_FreeValue(ctx, item);
break; break;
}
next_promise = JS_Call(ctx, promise_resolve, next_promise = JS_Call(ctx, promise_resolve,
this_val, 1, (JSValueConst *)&item); this_val, 1, (JSValueConst *)&item);
JS_FreeValue(ctx, item); JS_FreeValue(ctx, item);
@ -48666,8 +48674,10 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done); item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);
if (JS_IsException(item)) if (JS_IsException(item))
goto fail_reject; goto fail_reject;
if (done) if (done) {
JS_FreeValue(ctx, item);
break; break;
}
next_promise = JS_Call(ctx, promise_resolve, next_promise = JS_Call(ctx, promise_resolve,
this_val, 1, (JSValueConst *)&item); this_val, 1, (JSValueConst *)&item);
JS_FreeValue(ctx, item); JS_FreeValue(ctx, item);
@ -53781,8 +53791,10 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val,
v = JS_IteratorNext(ctx, stack[0], stack[1], 0, NULL, &done); v = JS_IteratorNext(ctx, stack[0], stack[1], 0, NULL, &done);
if (JS_IsException(v)) if (JS_IsException(v))
goto exception_close; goto exception_close;
if (done) if (done) {
JS_FreeValue(ctx, v);
break; break;
}
if (JS_DefinePropertyValueInt64(ctx, arr, k, v, JS_PROP_C_W_E | JS_PROP_THROW) < 0) if (JS_DefinePropertyValueInt64(ctx, arr, k, v, JS_PROP_C_W_E | JS_PROP_THROW) < 0)
goto exception_close; goto exception_close;
} }