using Jint.Native.Object;
using Jint.Runtime.Debugger;

#pragma warning disable 618

namespace Jint.Tests.Runtime.Debugger
{
    public class DebugHandlerTests
    {
        [Fact]
        public void AvoidsPauseRecursion()
        {
            // While the DebugHandler is in a paused state, it shouldn't relay further OnStep calls to Break/Step.
            // Such calls would occur e.g. if Step/Break event handlers evaluate accessors. Failing to avoid
            // reentrance in a multithreaded environment (e.g. using ManualResetEvent(Slim)) would cause
            // a deadlock.
            string script = @"
                var obj = { get name() { 'fail'; return 'Smith'; } };
                'target';
            ";

            var engine = new Engine(options => options.DebugMode().InitialStepMode(StepMode.Into));

            bool didPropertyAccess = false;

            engine.Debugger.Step += (sender, info) =>
            {
                // We should never reach "fail", because the only way it's executed is from
                // within this Step handler
                Assert.False(info.ReachedLiteral("fail"));

                if (info.ReachedLiteral("target"))
                {
                    var obj = info.CurrentScopeChain[0].GetBindingValue("obj") as ObjectInstance;
                    var prop = obj.GetOwnProperty("name");
                    // This is where reentrance would occur:
                    var value = engine.Invoke(prop.Get);
                    didPropertyAccess = true;
                }
                return StepMode.Into;
            };

            engine.Execute(script);

            Assert.True(didPropertyAccess);
        }
    }
}
