Skip to content

Commit 1185e4b

Browse files
committed
Add InternalException Event
Better track some of the internal exceptions.
1 parent 4aac247 commit 1185e4b

File tree

8 files changed

+168
-14
lines changed

8 files changed

+168
-14
lines changed

MonacoEditorComponent/CodeEditor.Events.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ public partial class CodeEditor
3131
/// </summary>
3232
public event TypedEventHandler<WebView, WebViewNewWindowRequestedEventArgs> OpenLinkRequested;
3333

34+
/// <summary>
35+
/// Called when an internal exception is encountered while executing a command. (for testing/reporting issues)
36+
/// </summary>
37+
public event TypedEventHandler<CodeEditor, Exception> InternalException;
38+
3439
/// <summary>
3540
/// Custom Keyboard Handler.
3641
/// </summary>
@@ -40,7 +45,9 @@ public partial class CodeEditor
4045

4146
private void WebView_DOMContentLoaded(WebView sender, WebViewDOMContentLoadedEventArgs args)
4247
{
48+
#if DEBUG
4349
Debug.WriteLine("DOM Content Loaded");
50+
#endif
4451
this._initialized = true;
4552
}
4653

@@ -64,7 +71,9 @@ private async void WebView_NavigationCompleted(WebView sender, WebViewNavigation
6471

6572
private void WebView_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
6673
{
74+
#if DEBUG
6775
Debug.WriteLine("Navigation Starting");
76+
#endif
6877
_parentAccessor = new ParentAccessor(this);
6978
_parentAccessor.RegisterAction("Loaded", async () =>
7079
{

MonacoEditorComponent/CodeEditor.cs

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using Collections.Generic;
22
using Monaco.Editor;
3+
using Monaco.Extensions;
34
using Monaco.Helpers;
45
using System;
56
using System.Collections.ObjectModel;
67
using System.ComponentModel;
8+
using System.Diagnostics;
79
using System.Runtime.CompilerServices;
810
using System.Threading.Tasks;
911
using Windows.Foundation;
@@ -64,7 +66,8 @@ public CodeEditor()
6466
// Register for changes
6567
this.Options.PropertyChanged += async (s, p) =>
6668
{
67-
await this.InvokeScriptAsync("updateOptions", new string[] { (s as IEditorConstructionOptions)?.ToJson() });
69+
// TODO: Check for Language property and call other method instead?
70+
await this.InvokeScriptAsync("updateOptions", new string[] { (s as IEditorConstructionOptions)?.ToJson() });
6871
};
6972
}
7073

@@ -99,20 +102,27 @@ protected override void OnApplyTemplate()
99102
base.OnApplyTemplate();
100103
}
101104

102-
internal async Task<string> SendScriptAsync(string script)
105+
internal async Task<string> SendScriptAsync(string script,
106+
[CallerMemberName] string member = null,
107+
[CallerFilePath] string file = null,
108+
[CallerLineNumber] int line = 0)
103109
{
104110
if (_initialized)
105111
{
106-
if (Dispatcher.HasThreadAccess)
112+
try
107113
{
108-
return await this._view.InvokeScriptAsync("eval", new string[] { script });
114+
return await this._view.RunScriptAsync(script);
109115
}
110-
else
116+
catch (Exception e)
111117
{
112-
return await Dispatcher.RunTaskAsync(async () => {
113-
return await _view.InvokeScriptAsync("eval", new string[] { script });
114-
});
115-
}
118+
InternalException?.Invoke(this, new JavaScriptExecutionException(member, file, line, script, e));
119+
}
120+
}
121+
else
122+
{
123+
#if DEBUG
124+
Debug.WriteLine("WARNING: Tried to call '" + script + "' before initialized.");
125+
#endif
116126
}
117127

118128
return string.Empty;
@@ -124,16 +134,37 @@ internal async Task<string> InvokeScriptAsync(string method, params string[] arg
124134
{
125135
if (Dispatcher.HasThreadAccess)
126136
{
127-
return await this._view.InvokeScriptAsync(method, args);
137+
try
138+
{
139+
return await this._view.InvokeScriptAsync(method, args);
140+
}
141+
catch (Exception e)
142+
{
143+
InternalException?.Invoke(this, e);
144+
}
128145
}
129146
else
130147
{
131148
return await Dispatcher.RunTaskAsync(async () =>
132149
{
133-
return await this._view.InvokeScriptAsync(method, args);
150+
try
151+
{
152+
return await this._view.InvokeScriptAsync(method, args);
153+
}
154+
catch (Exception e)
155+
{
156+
InternalException?.Invoke(this, e);
157+
return string.Empty;
158+
}
134159
});
135160
}
136161
}
162+
else
163+
{
164+
#if DEBUG
165+
Debug.WriteLine("WARNING: Tried to call " + method + " before initialized.");
166+
#endif
167+
}
137168

138169
return string.Empty;
139170
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
using Monaco.Helpers;
2+
using System;
3+
using System.Runtime.CompilerServices;
4+
using System.Threading.Tasks;
5+
using Windows.Data.Json;
6+
using Windows.UI.Xaml.Controls;
7+
8+
namespace Monaco.Extensions
9+
{
10+
internal static class WebViewExtensions
11+
{
12+
public static async Task<string> RunScriptAsync(
13+
this WebView _view,
14+
string script,
15+
[CallerMemberName] string member = null,
16+
[CallerFilePath] string file = null,
17+
[CallerLineNumber] int line = 0)
18+
{
19+
var fullscript = "try {\n" +
20+
script +
21+
"\n} catch (err) { JSON.stringify({ wv_internal_error: true, message: err.message, description: err.description, number: err.number, stack: err.stack }); }";
22+
23+
if (_view.Dispatcher.HasThreadAccess)
24+
{
25+
try
26+
{
27+
return await RunScriptHelperAsync(_view, fullscript);
28+
}
29+
catch (Exception e)
30+
{
31+
throw new JavaScriptExecutionException(member, file, line, script, e);
32+
}
33+
}
34+
else
35+
{
36+
return await _view.Dispatcher.RunTaskAsync(async () =>
37+
{
38+
try
39+
{
40+
return await RunScriptHelperAsync(_view, fullscript);
41+
}
42+
catch (Exception e)
43+
{
44+
throw new JavaScriptExecutionException(member, file, line, script, e);
45+
}
46+
});
47+
}
48+
}
49+
50+
private static async Task<string> RunScriptHelperAsync(WebView _view, string script)
51+
{
52+
var returnstring = await _view.InvokeScriptAsync("eval", new string[] { script });
53+
54+
if (JsonObject.TryParse(returnstring, out JsonObject result))
55+
{
56+
if (result.ContainsKey("wv_internal_error") && result["wv_internal_error"].ValueType == JsonValueType.Boolean && result["wv_internal_error"].GetBoolean())
57+
{
58+
throw new JavaScriptInnerException(result["message"].GetString(), result["stack"].GetString());
59+
}
60+
}
61+
62+
return returnstring;
63+
}
64+
}
65+
66+
internal sealed class JavaScriptExecutionException : Exception
67+
{
68+
public string Script { get; private set; }
69+
70+
public string Member { get; private set; }
71+
72+
public string FileName { get; private set; }
73+
74+
public int LineNumber { get; private set; }
75+
76+
public JavaScriptExecutionException(string member, string filename, int line, string script, Exception inner)
77+
: base("Error Executing JavaScript Code", inner)
78+
{
79+
this.Member = member;
80+
this.FileName = filename;
81+
this.LineNumber = line;
82+
this.Script = script;
83+
}
84+
}
85+
86+
internal sealed class JavaScriptInnerException : Exception
87+
{
88+
public string JavaScriptStackTrace { get; private set; } // TODO Use Enum of JS error types https://www.w3schools.com/js/js_errors.asp
89+
90+
public JavaScriptInnerException(string message, string stack)
91+
: base(message)
92+
{
93+
this.JavaScriptStackTrace = stack;
94+
}
95+
}
96+
}

MonacoEditorComponent/Helpers/DebugLogger.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ public sealed class DebugLogger
88
{
99
public void Log(string message)
1010
{
11+
#if DEBUG
1112
Debug.WriteLine(message);
13+
#endif
1214
}
1315
}
1416
}

MonacoEditorComponent/Helpers/ThemeListener.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ public ThemeListener()
4444

4545
private void _accessible_HighContrastChanged(AccessibilitySettings sender, object args)
4646
{
47+
#if DEBUG
4748
Debug.WriteLine("HighContrast Changed");
49+
#endif
4850

4951
UpdateProperties();
5052
}
@@ -59,7 +61,9 @@ await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.Co
5961
if (CurrentTheme != Application.Current.RequestedTheme ||
6062
IsHighContrast != _accessible.HighContrast)
6163
{
64+
#if DEBUG
6265
Debug.WriteLine("Color Values Changed");
66+
#endif
6367

6468
UpdateProperties();
6569
}
@@ -71,7 +75,9 @@ private void CoreWindow_Activated(Windows.UI.Core.CoreWindow sender, Windows.UI.
7175
if (CurrentTheme != Application.Current.RequestedTheme ||
7276
IsHighContrast != _accessible.HighContrast)
7377
{
78+
#if DEBUG
7479
Debug.WriteLine("CoreWindow Activated Changed");
80+
#endif
7581

7682
UpdateProperties();
7783
}

MonacoEditorComponent/MonacoEditor.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@
2828
var contexts = {};
2929
var decorations = [];
3030

31-
Debug.log("Starting");
31+
Debug.log("Starting Monaco Load");
3232
require.config({ paths: { 'vs': 'ms-appx-web:///Monaco/monaco-editor/min/vs' }});
3333
require(['vs/editor/editor.main'], function () {
34+
Debug.log("Grabbing Monaco Options");
35+
3436
let opt = getOptions();
3537
opt["value"] = Parent.getValue("Text");
3638

37-
editor = monaco.editor.create(document.getElementById('container'), opt);
39+
editor = monaco.editor.create(document.getElementById('container'), opt);
3840
model = editor.getModel();
3941

4042
// Listen for Content Changes
@@ -54,7 +56,7 @@
5456
window.addEventListener("resize", () => {
5557
editor.layout();
5658
});
57-
59+
5860
// Disable WebView Scrollbar so Monaco Scrollbar can do heavy lifting
5961
document.body.style.overflow = 'hidden';
6062

MonacoEditorComponent/MonacoEditorComponent.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
<Compile Include="CodeEditor.cs" />
115115
<Compile Include="CodeEditor.Methods.cs" />
116116
<Compile Include="CodeEditor.Properties.cs" />
117+
<Compile Include="Extensions\WebViewExtensions.cs" />
117118
<Compile Include="Helpers\DebugLogger.cs" />
118119
<Compile Include="Helpers\DispatcherTaskExtensions.cs" />
119120
<Compile Include="Helpers\KeyboardListener.cs" />

MonacoEditorTestApp/MainPage.xaml.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,16 @@ public MainPage()
4343
Editor.Loaded += Editor_Loaded;
4444
Editor.OpenLinkRequested += Editor_OpenLinkRequest;
4545

46+
Editor.InternalException += Editor_InternalException;
47+
4648
this.ButtonHighlightRange_Click(null, null);
4749
}
4850

51+
private void Editor_InternalException(CodeEditor sender, Exception args)
52+
{
53+
// This shouldn't happen, if it does, then it's a bug.
54+
}
55+
4956
private async void Editor_Loading(object sender, RoutedEventArgs e)
5057
{
5158
// Ready for Code

0 commit comments

Comments
 (0)