public void ProcessChangeLiveResponse() {
            // Arrange
            const int commandId = 3;
            const int moduleId = 5;
            const string fileName = "fileName.js";
            var module = new NodeModule(moduleId, fileName);
            var changeLiveCommand = new ChangeLiveCommand(commandId, module);

            // Act
            changeLiveCommand.ProcessResponse(SerializationTestData.GetChangeLiveResponse());

            // Assert
            Assert.AreEqual(commandId, changeLiveCommand.Id);
            Assert.IsTrue(changeLiveCommand.Updated);
            Assert.IsTrue(changeLiveCommand.StackModified);
        }
        public void CreateChangeLiveCommand() {
            // Arrange
            const int commandId = 3;
            const int moduleId = 5;
            const string fileName = "fileName.js";
            const string source = "source";
            string wrappedSource = string.Format("{0}{1}{2}", NodeConstants.ScriptWrapBegin, source, NodeConstants.ScriptWrapEnd.Replace("\n", @"\n"));
            var module = new NodeModule(moduleId, fileName) { Source = source };

            // Act
            var changeLiveCommand = new ChangeLiveCommand(commandId, module);

            // Assert
            Assert.AreEqual(commandId, changeLiveCommand.Id);
            Assert.AreEqual(
                string.Format(
                    "{{\"command\":\"changelive\",\"seq\":{0},\"type\":\"request\",\"arguments\":{{\"script_id\":{1},\"new_source\":\"{2}\",\"preview_only\":false}}}}",
                    commandId, moduleId, wrappedSource),
                changeLiveCommand.ToString());
        }
        public void CreateSetBreakpointCommand() {
            // Arrange
            const int commandId = 3;
            const int moduleId = 5;
            const int line = 2;
            const int column = 0;
            const string fileName = "module.js";
            var module = new NodeModule(moduleId, fileName);
            var breakOn = new BreakOn(BreakOnKind.Equal, 2);
            var position = new FilePosition(fileName, line, column);
            var breakpoint = new NodeBreakpoint(null, position, true, breakOn, null);

            // Act
            var setBreakpointCommand = new SetBreakpointCommand(commandId, module, breakpoint, false, false);

            // Assert
            Assert.AreEqual(commandId, setBreakpointCommand.Id);
            Assert.AreEqual(
                string.Format(
                    "{{\"command\":\"setbreakpoint\",\"seq\":{0},\"type\":\"request\",\"arguments\":{{\"line\":{1},\"column\":{2},\"type\":\"scriptId\",\"target\":{3},\"ignoreCount\":1}}}}",
                    commandId, line, column, module.Id),
                setBreakpointCommand.ToString());
        }
 public ModuleLoadedEventArgs(NodeModule module) {
     Module = module;
 }
        private async Task<bool> ProcessBreakpointBreakAsync(
            NodeModule brokeIn,
            IEnumerable<NodeBreakpointBinding> breakpointBindings,
            bool testFullyBound,
            CancellationToken cancellationToken = new CancellationToken()) {
            // Process breakpoint binding
            var hitBindings = new List<NodeBreakpointBinding>();

            // Iterate over breakpoint bindings, processing them as fully bound or not
            int currentLine = MainThread.TopStackFrame.Line;
            foreach (NodeBreakpointBinding breakpointBinding in breakpointBindings) {
                // Handle normal (fully bound) breakpoint binding
                if (breakpointBinding.FullyBound) {
                    if (!testFullyBound || await breakpointBinding.TestAndProcessHitAsync().ConfigureAwait(false)) {
                        hitBindings.Add(breakpointBinding);
                    }
                } else {
                    // Handle fixed-up breakpoint binding
                    // Rebind breakpoint
                    await RemoveBreakpointAsync(breakpointBinding, cancellationToken).ConfigureAwait(false);

                    NodeBreakpoint breakpoint = breakpointBinding.Breakpoint;

                    // If this breakpoint has been deleted, then do not try to rebind it after removing it from the list,
                    // and do not treat this binding as hit.
                    if (breakpoint.Deleted) {
                        continue;
                    }

                    SetBreakpointCommand result = await SetBreakpointAsync(breakpoint, cancellationToken: cancellationToken).ConfigureAwait(false);
                    
                    // Treat rebound breakpoint binding as fully bound
                    NodeBreakpointBinding reboundbreakpointBinding = CreateBreakpointBinding(breakpoint, result.BreakpointId, result.ScriptId, breakpoint.GetPosition(SourceMapper).FileName, result.Line, result.Column, true);
                    HandleBindBreakpointSuccess(reboundbreakpointBinding, breakpoint);

                    // Handle invalid-line fixup (second bind matches current line)
                    if (reboundbreakpointBinding.Target.Line == currentLine && await reboundbreakpointBinding.TestAndProcessHitAsync().ConfigureAwait(false)) {
                        hitBindings.Add(reboundbreakpointBinding);
                    }
                }
            }

            // Handle last processed breakpoint binding by breaking with breakpoint hit events
            List<NodeBreakpointBinding> matchedBindings = ProcessBindings(brokeIn.JavaScriptFileName, hitBindings).ToList();

            // Fire breakpoint hit event(s)
            EventHandler<BreakpointHitEventArgs> breakpointHit = BreakpointHit;
            foreach (NodeBreakpointBinding binding in matchedBindings) {
                await binding.ProcessBreakpointHitAsync(cancellationToken).ConfigureAwait(false);
                if (breakpointHit != null) {
                    breakpointHit(this, new BreakpointHitEventArgs(binding, MainThread));
                }
            }

            return matchedBindings.Count != 0;
        }
        /// <summary>
        /// Updates a module content while debugging.
        /// </summary>
        /// <param name="module">Node module.</param>
        /// <returns>Operation result.</returns>
        internal async Task<bool> UpdateModuleSourceAsync(NodeModule module) {
            module.Source = File.ReadAllText(module.JavaScriptFileName);

            var changeLiveCommand = new ChangeLiveCommand(CommandId, module);

            // Check whether update was successfull
            if (!await TrySendRequestAsync(changeLiveCommand).ConfigureAwait(false) ||
                !changeLiveCommand.Updated) {
                return false;
            }

            // Make step into and update stacktrace if required
            if (changeLiveCommand.StackModified) {
                var continueCommand = new ContinueCommand(CommandId, SteppingKind.Into);
                await TrySendRequestAsync(continueCommand).ConfigureAwait(false);
                await CompleteSteppingAsync(false).ConfigureAwait(false);
            }

            return true;
        }
        /// <summary>
        /// Gets or adds a new module.
        /// </summary>
        /// <param name="module">New module.</param>
        /// <param name="value">Existing module.</param>
        /// <param name="stackFrame">The stack frame linked to the module.</param>
        /// <returns>True if module was added otherwise false.</returns>
        private bool GetOrAddModule(NodeModule module, out NodeModule value, NodeStackFrame stackFrame = null) {
            value = null;
            string javaScriptFileName = module.JavaScriptFileName;
            int? line = null, column = null;

            if (string.IsNullOrEmpty(javaScriptFileName) ||
                javaScriptFileName == NodeVariableType.UnknownModule ||
                javaScriptFileName.StartsWith("binding:")) {
                return false;
            }

            // Get local JS file name
            javaScriptFileName = FileNameMapper.GetLocalFileName(javaScriptFileName);

            // Try to get mapping for JS file
            if(stackFrame != null) {
                line = stackFrame.Line;
                column = stackFrame.Column;
            }
            string originalFileName = SourceMapper.GetOriginalFileName(javaScriptFileName, line, column);

            if (originalFileName == null) {
                module = new NodeModule(module.Id, javaScriptFileName);
            } else {
                string directoryName = Path.GetDirectoryName(javaScriptFileName) ?? string.Empty;
                string fileName = CommonUtils.GetAbsoluteFilePath(directoryName, originalFileName.Replace('/', '\\'));

                module = new NodeModule(module.Id, fileName, javaScriptFileName);
            }

            // Check whether module already exits
            if (_modules.TryGetValue(module.FileName, out value)) {
                return false;
            }

            value = module;

            // Add module
            _modules[module.FileName] = module;

            return true;
        }
        public void CreateSetBreakpointCommandWithNullBreakpoint() {
            // Arrange
            const int commandId = 3;
            const int moduleId = 5;
            const string fileName = "module.js";
            var module = new NodeModule(moduleId, fileName);
            SetBreakpointCommand setBreakpointCommand = null;
            Exception exception = null;

            // Act
            try {
                setBreakpointCommand = new SetBreakpointCommand(commandId, module, null, false, false);
            } catch (Exception e) {
                exception = e;
            }

            // Assert
            Assert.IsNull(setBreakpointCommand);
            Assert.IsNotNull(exception);
            Assert.IsInstanceOfType(exception, typeof (ArgumentNullException));
        }
        public void ProcessSetBreakpointResponse() {
            // Arrange
            const int commandId = 3;
            const int moduleId = 33;
            const int line = 2;
            const int column = 0;
            const string fileName = "module.js";
            var module = new NodeModule(moduleId, fileName);
            var breakOn = new BreakOn(BreakOnKind.Equal, 2);
            var position = new FilePosition(fileName, line, column);
            var breakpoint = new NodeBreakpoint(null, position, true, breakOn, null);
            var setBreakpointCommand = new SetBreakpointCommand(commandId, module, breakpoint, false, false);
            JObject breakpointResponse = SerializationTestData.GetSetBreakpointResponse();

            // Act
            setBreakpointCommand.ProcessResponse(breakpointResponse);

            // Assert
            Assert.AreEqual(2, setBreakpointCommand.BreakpointId);
            Assert.AreEqual(0, setBreakpointCommand.Column);
            Assert.AreEqual(0, setBreakpointCommand.Line);
            Assert.AreEqual(false, setBreakpointCommand.Running);
            Assert.AreEqual(33, setBreakpointCommand.ScriptId);
        }
 public ModuleLoadedEventArgs(NodeModule module)
 {
     _module = module;
 }