private object Resume(Context cx, Scriptable scope, int operation, object value)
{
if (savedState == null)
{
if (operation == GENERATOR_CLOSE)
{
return Undefined.instance;
}
object thrown;
if (operation == GENERATOR_THROW)
{
thrown = value;
}
else
{
thrown = NativeIterator.GetStopIterationObject(scope);
}
throw new JavaScriptException(thrown, lineSource, lineNumber);
}
try
{
lock (this)
{
// generator execution is necessarily single-threaded and
// non-reentrant.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=349263
if (locked)
{
throw ScriptRuntime.TypeError0("msg.already.exec.gen");
}
locked = true;
}
return function.ResumeGenerator(cx, scope, operation, savedState, value);
}
catch (NativeGenerator.GeneratorClosedException)
{
// On closing a generator in the compile path, the generator
// throws a special exception. This ensures execution of all pending
// finalizers and will not get caught by user code.
return Undefined.instance;
}
catch (RhinoException e)
{
lineNumber = e.LineNumber();
lineSource = e.LineSource();
savedState = null;
throw;
}
finally
{
lock (this)
{
locked = false;
}
if (operation == GENERATOR_CLOSE)
{
savedState = null;
}
}
}