зеркало из https://github.com/mozilla/pjs.git
Final patch for bug 349012 (r=igor/mrbkap).
This commit is contained in:
Родитель
b015387bb5
Коммит
36ea09c432
|
@ -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,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));
|
||||
|
|
|
@ -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 {
|
||||
|
|
Загрузка…
Ссылка в новой задаче