Example #1
0
        public void Load(string path)
        {
            try
            {
                string source = File.ReadAllText(path);
                var    script = new ScriptData(GetId(path), path, source);
                scripts.Add(script.Id, script);
                debugger.AddScript(script);
            }
            catch (Exception ex) when(ex is FileNotFoundException || ex is PathTooLongException || ex is DirectoryNotFoundException || ex is IOException || ex is UnauthorizedAccessException)
            {
                string fileName = Path.GetFileName(path);

                throw new ScriptLoaderException($"Could not load '{fileName}': {ex.Message}", ex);
            }
        }
        /// <summary>
        /// Adds a script to the execution queue.
        /// </summary>
        /// <param name="data">Script metadata</param>
        public void AddScript(ScriptData data)
        {
            // We need to parse the script ourselves (rather than using the Jint Engine constructor
            // that takes the source code as string) - in order to get the parser to assign our ID
            // as Source in the AST nodes' Location property.
            var parser = new JavaScriptParser(data.Script, new ParserOptions(data.Id)
            {
                AdaptRegexp = true,
                Loc         = true,
                Tolerant    = true
            });

            data.Ast = parser.ParseScript();

            scripts.Add(data);
        }
        /// <summary>
        /// Adds breakpoint
        /// </summary>
        /// <param name="scriptId">ID of script</param>
        /// <param name="line">Line number (starting from 1)</param>
        /// <returns></returns>
        public bool TryAddBreakPoint(string scriptId, int line)
        {
            ScriptData script = GetScript(scriptId);

            if (script == null)
            {
                return(false);
            }
            var node = script.GetNodeAtLine(script.Ast, line);

            if (node == null)
            {
                return(false);
            }
            engine.BreakPoints.Add(new BreakPoint(node.Location.Source, node.Location.Start.Line, node.Location.Start.Column));
            return(true);
        }
 /// <summary>
 /// Executes the scripts in the debugger.
 /// </summary>
 public void Execute()
 {
     IsRunning = true;
     cts       = new CancellationTokenSource();
     try
     {
         // We run the debugger script execution on a separate thread. Why?
         // In a GUI app this is necessary, since Jint signals reaching a breakpoint
         // or step by triggering an event. When the event handler returns, script execution
         // continues. That means we'd be blocking the UI thread until the entire script is done
         // executing (if it ever is).
         // In a console app, it would be doable - do e.g. a Console.ReadLine when handling
         // the Step/Break event. However, we also want to be able to run a script without stepping,
         // and then stop/pause it if, for example, it ends up in an infinite loop. So, even in our
         // console app, the "UI thread" (Console read/write) must not be blocked while Jint is
         // executing the script.
         Task.Run(() =>
         {
             try
             {
                 int currentScriptIndex = 0;
                 while (currentScriptIndex < scripts.Count)
                 {
                     ScriptData script = scripts[currentScriptIndex];
                     engine.Execute(script.Ast);
                     currentScriptIndex++;
                 }
             }
             catch (CancelExecutionException)
             {
                 // Do nothing - the exception is just used to signal cancellation.
             }
             Done?.Invoke();
         }, cts.Token);
     }
     finally
     {
         IsRunning = false;
     }
 }