Skip to content

Commit fad85d9

Browse files
authored
Propagate exceptions in Iterator.concat (#1256)
test262 took a 180 degree turn because the test that is fixed by this commit is the polar opposite of what was tested by the test suite when I originally added Iterator.concat. The old behavior was not very efficient, so good for them for changing their minds, but next time please do so before I spend an hour implementing it, thank you very much.
1 parent f889712 commit fad85d9

File tree

2 files changed

+15
-46
lines changed

2 files changed

+15
-46
lines changed

quickjs.c

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -41781,21 +41781,23 @@ static void js_iterator_concat_mark(JSRuntime *rt, JSValueConst val,
4178141781
}
4178241782

4178341783
static JSValue js_iterator_concat_next(JSContext *ctx, JSValueConst this_val,
41784-
int argc, JSValueConst *argv)
41784+
int argc, JSValueConst *argv,
41785+
int *pdone, int magic)
4178541786
{
4178641787
JSValue iter, item, next, val, *obj, *meth;
4178741788
JSIteratorConcatData *it;
41788-
JSPropertyDescriptor d;
41789-
int done, ret;
41789+
int done;
4179041790

4179141791
it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_CONCAT);
4179241792
if (!it)
4179341793
return JS_EXCEPTION;
4179441794
if (it->running)
4179541795
return JS_ThrowTypeError(ctx, "already running");
4179641796
next:
41797-
if (it->index >= it->count)
41798-
return js_create_iterator_result(ctx, JS_UNDEFINED, /*done*/true);
41797+
if (it->index >= it->count) {
41798+
*pdone = true;
41799+
return JS_UNDEFINED;
41800+
}
4179941801
obj = &it->values[it->index + 0];
4180041802
meth = &it->values[it->index + 1];
4180141803
iter = it->iter;
@@ -41817,8 +41819,10 @@ static JSValue js_iterator_concat_next(JSContext *ctx, JSValueConst this_val,
4181741819
it->running = false;
4181841820
if (JS_IsException(item))
4181941821
return JS_EXCEPTION;
41820-
if (!done)
41821-
return js_create_iterator_result(ctx, item, /*done*/false);
41822+
if (!done) {
41823+
*pdone = false;
41824+
return item;
41825+
}
4182241826
// done==1 means really done, done==2 means "unknown, inspect object"
4182341827
if (done == 2) {
4182441828
val = JS_GetProperty(ctx, item, JS_ATOM_done);
@@ -41839,38 +41843,10 @@ static JSValue js_iterator_concat_next(JSContext *ctx, JSValueConst this_val,
4183941843
it->index += 2;
4184041844
goto next;
4184141845
}
41842-
// not done, construct { done: false, value: xxx } object
41843-
// copy .value verbatim from source object, spec doesn't
41844-
// allow dereferencing getters here
41845-
d = (JSPropertyDescriptor){
41846-
.value = JS_UNDEFINED,
41847-
.getter = JS_UNDEFINED,
41848-
.setter = JS_UNDEFINED,
41849-
};
41850-
ret = JS_GetOwnProperty(ctx, &d, item, JS_ATOM_value);
41846+
val = JS_GetProperty(ctx, item, JS_ATOM_value);
4185141847
JS_FreeValue(ctx, item);
41852-
if (ret < 0)
41853-
return JS_EXCEPTION;
41854-
if (d.flags & JS_PROP_GETSET) {
41855-
d.flags |= JS_PROP_HAS_GET | JS_PROP_HAS_SET;
41856-
} else {
41857-
d.flags |= JS_PROP_HAS_VALUE;
41858-
}
41859-
item = JS_NewObject(ctx);
41860-
if (JS_IsException(item))
41861-
goto fail;
41862-
if (JS_DefinePropertyValue(ctx, item, JS_ATOM_done, JS_FALSE,
41863-
JS_PROP_C_W_E) < 0) {
41864-
goto fail;
41865-
}
41866-
if (JS_DefineProperty(ctx, item, JS_ATOM_value, d.value, d.getter,
41867-
d.setter, d.flags | JS_PROP_C_W_E) < 0) {
41868-
fail:
41869-
JS_FreeValue(ctx, item);
41870-
item = JS_EXCEPTION;
41871-
}
41872-
js_free_desc(ctx, &d);
41873-
return item;
41848+
*pdone = false;
41849+
return val;
4187441850
}
4187541851

4187641852
static JSValue js_iterator_concat_return(JSContext *ctx, JSValueConst this_val,
@@ -41902,13 +41878,8 @@ static JSValue js_iterator_concat_return(JSContext *ctx, JSValueConst this_val,
4190241878
return ret;
4190341879
}
4190441880

41905-
// note: |next| and |return| don't use JS_ITERATOR_NEXT_DEF because |next|
41906-
// has to return a full { value: xxx, done: xxx } step object - it must
41907-
// copy getters and setters from the inner iterator's step object
41908-
// slightly inefficient because of the intermediate step object that is
41909-
// created but that can't be helped right now
4191041881
static const JSCFunctionListEntry js_iterator_concat_proto_funcs[] = {
41911-
JS_CFUNC_DEF("next", 1, js_iterator_concat_next ),
41882+
JS_ITERATOR_NEXT_DEF("next", 1, js_iterator_concat_next, 0 ),
4191241883
JS_CFUNC_DEF("return", 1, js_iterator_concat_return ),
4191341884
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Iterator Concat", JS_PROP_CONFIGURABLE ),
4191441885
};

test262_errors.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/iterator-result-reje
1717
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/iterator-result-rejected-promise-close.js:74: strict mode: TypeError: $DONE() not called
1818
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-result-poisoned-wrapper.js:81: TypeError: $DONE() not called
1919
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-result-poisoned-wrapper.js:81: strict mode: TypeError: $DONE() not called
20-
test262/test/built-ins/Iterator/concat/next-method-returns-throwing-value.js:25: Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all
21-
test262/test/built-ins/Iterator/concat/next-method-returns-throwing-value.js:25: strict mode: Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all
2220
test262/test/built-ins/RegExp/property-escapes/generated/Script_-_Unknown.js:16: SyntaxError: unknown unicode script
2321
test262/test/built-ins/RegExp/property-escapes/generated/Script_-_Unknown.js:16: strict mode: SyntaxError: unknown unicode script
2422
test262/test/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Unknown.js:16: SyntaxError: unknown unicode script

0 commit comments

Comments
 (0)