Final patch for bug 349012 (r=igor/mrbkap).

This commit is contained in:
brendan%mozilla.org 2006-08-19 06:17:49 +00:00
Родитель b015387bb5
Коммит 36ea09c432
3 изменённых файлов: 43 добавлений и 36 удалений

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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,11 +768,21 @@ 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_RUNNING) {
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;
}
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_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,
@ -795,6 +791,9 @@ generator_send_sub(JSContext *cx, JSObject *obj, JSGenerator *gen,
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));

Просмотреть файл

@ -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 {