From 36ea09c4320a361ba52900bef1c2f0ba411e3501 Mon Sep 17 00:00:00 2001 From: "brendan%mozilla.org" Date: Sat, 19 Aug 2006 06:17:49 +0000 Subject: [PATCH] Final patch for bug 349012 (r=igor/mrbkap). --- js/src/jsinterp.c | 2 +- js/src/jsiter.c | 60 +++++++++++++++++++++++++---------------------- js/src/jsiter.h | 17 ++++++++------ 3 files changed, 43 insertions(+), 36 deletions(-) diff --git a/js/src/jsinterp.c b/js/src/jsinterp.c index 8801e32ff9c..87b9c9e82ed 100644 --- a/js/src/jsinterp.c +++ b/js/src/jsinterp.c @@ -6065,7 +6065,7 @@ interrupt: BEGIN_CASE(JSOP_YIELD) ASSERT_NOT_THROWING(cx); - if (FRAME_TO_GENERATOR(fp)->state == JSGEN_CLOSING) { + if (FRAME_TO_GENERATOR(fp)->state & JSGEN_CLOSING) { str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, fp->argv[-2], NULL); if (str) { diff --git a/js/src/jsiter.c b/js/src/jsiter.c index c1f4e818ca5..6d59dbd42c3 100644 --- a/js/src/jsiter.c +++ b/js/src/jsiter.c @@ -755,20 +755,6 @@ js_NewGenerator(JSContext *cx, JSStackFrame *fp) return NULL; } -static JSBool -ReportNestingGenerator(JSContext *cx, jsval *argv) -{ - JSString *str; - - str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, argv[-1], NULL); - if (str) { - JS_ReportErrorNumberUC(cx, js_GetErrorMessage, NULL, - JSMSG_NESTING_GENERATOR, - JSSTRING_CHARS(str)); - } - return JS_FALSE; -} - /* * Common subroutine of generator_send and generator_close. */ @@ -782,19 +768,32 @@ generator_send_sub(JSContext *cx, JSObject *obj, JSGenerator *gen, JSBool ok; jsval junk; - if (gen->state == JSGEN_RUNNING) - return ReportNestingGenerator(cx, argv); - - if (gen->state == JSGEN_NEWBORN && argc != 0 && !JSVAL_IS_VOID(argv[0])) { - str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, argv[0], NULL); + if (gen->state & JSGEN_RUNNING) { + str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, argv[-1], + NULL); if (str) { JS_ReportErrorNumberUC(cx, js_GetErrorMessage, NULL, - JSMSG_BAD_GENERATOR_SEND, + JSMSG_NESTING_GENERATOR, JSSTRING_CHARS(str)); } return JS_FALSE; } + if (gen->state == JSGEN_NEWBORN) { + if (argc != 0 && !JSVAL_IS_VOID(argv[0])) { + str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, argv[0], + NULL); + if (str) { + JS_ReportErrorNumberUC(cx, js_GetErrorMessage, NULL, + JSMSG_BAD_GENERATOR_SEND, + JSSTRING_CHARS(str)); + } + return JS_FALSE; + } + + gen->state = JSGEN_OPEN; + } + fp = cx->fp; arena = cx->stackPool.current; cx->stackPool.current = &gen->arena; @@ -803,9 +802,9 @@ generator_send_sub(JSContext *cx, JSObject *obj, JSGenerator *gen, /* Store the argument to send as the result of the yield expression. */ gen->frame.sp[-1] = (argc != 0) ? argv[0] : JSVAL_VOID; - gen->state = JSGEN_RUNNING; + gen->state |= JSGEN_RUNNING; ok = js_Interpret(cx, gen->frame.pc, &junk); - gen->state = JSGEN_OPEN; + gen->state &= ~JSGEN_RUNNING; cx->fp = fp; cx->stackPool.current = arena; @@ -864,6 +863,7 @@ generator_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, { JSGenerator *gen; jsval genexit, exn; + JSBool ok; JSClass *clasp; JSString *str; @@ -874,9 +874,6 @@ generator_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, if (!gen || gen->state == JSGEN_CLOSED) return JS_TRUE; - if (gen->state == JSGEN_RUNNING) - return ReportNestingGenerator(cx, argv); - if (!js_FindClassObject(cx, NULL, INT_TO_JSID(JSProto_GeneratorExit), &genexit)) { return JS_FALSE; @@ -884,11 +881,18 @@ generator_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, /* Throw GeneratorExit at the generator and ignore the returned status. */ JS_SetPendingException(cx, genexit); - gen->state = JSGEN_CLOSING; - generator_send_sub(cx, obj, gen, 0, argv, rval); + gen->state |= JSGEN_CLOSING; + ok = generator_send_sub(cx, obj, gen, 0, argv, rval); gen->state = JSGEN_CLOSED; - if (cx->throwing) { + if (!cx->throwing) { + /* + * If out-of-memory was reported or the branch callback canceled the + * generator, fail immediately. + */ + if (!ok) + return JS_FALSE; + } else { exn = cx->exception; if (!JSVAL_IS_PRIMITIVE(exn)) { clasp = OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(exn)); diff --git a/js/src/jsiter.h b/js/src/jsiter.h index 46a1ceee185..2f860828b4a 100644 --- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -1,5 +1,5 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=80: + * vim: set ts=8 sw=4 et tw=78: * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -94,13 +94,16 @@ js_ThrowStopIteration(JSContext *cx, JSObject *obj); #if JS_HAS_GENERATORS -/* Ordered list of generator state codes. */ +/* + * Generator state codes are actually flag bits, to allow RUNNING to be added + * to OPEN, and CLOSING to be added to OPEN and RUNNING. + */ typedef enum JSGeneratorState { - JSGEN_NEWBORN, /* not yet started */ - JSGEN_OPEN, /* started by a .next() or .send(undefined) call */ - JSGEN_RUNNING, /* currently executing via .next(), etc., call */ - JSGEN_CLOSING, /* close method is doing .send(GeneratorExit) */ - JSGEN_CLOSED /* closed, cannot be started or closed again */ + JSGEN_NEWBORN = 0, /* not yet started */ + JSGEN_OPEN = 1, /* started by a .next() or .send(undefined) call */ + JSGEN_RUNNING = 2, /* currently executing via .next(), etc., call */ + JSGEN_CLOSING = 4, /* close method is doing .send(GeneratorExit) */ + JSGEN_CLOSED = 8 /* closed, cannot be started or closed again */ } JSGeneratorState; struct JSGenerator {