Skip to content

Commit aecb628

Browse files
committed
Handle if no object is passed to BrowserWindow ctor
- Add JToken to JavaScriptValue converter helper
1 parent 0b25f96 commit aecb628

File tree

5 files changed

+141
-14
lines changed

5 files changed

+141
-14
lines changed

Electrino/win10/Electrino/Electrino.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@
135135
<Compile Include="JS\JSProcess.cs" />
136136
<Compile Include="JS\JSRequire.cs" />
137137
<Compile Include="JS\JSUrl.cs" />
138+
<Compile Include="JS\JTokenToJavaScriptValueConverter.cs" />
138139
<Compile Include="MainPage.xaml.cs">
139140
<DependentUpon>MainPage.xaml</DependentUpon>
140141
</Compile>

Electrino/win10/Electrino/JS/JSBrowserWindow.cs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
6-
using ChakraHost.Hosting;
7-
using System.Diagnostics;
1+
using ChakraHost.Hosting;
82
using Newtonsoft.Json.Linq;
3+
using System;
4+
using System.Collections.Generic;
95

106
namespace Electrino.JS
117
{
@@ -23,7 +19,16 @@ protected override JavaScriptValue Main(JavaScriptValue callee, bool isConstruct
2319
return JavaScriptValue.CreateTypeError(JavaScriptValue.FromString("BrowserWindow must be constructed"));
2420
}
2521

26-
var options = JavaScriptValueToJTokenConverter.Convert(arguments[1]);
22+
JToken options;
23+
try
24+
{
25+
options = JavaScriptValueToJTokenConverter.Convert(arguments[1]);
26+
}
27+
catch (Exception)
28+
{
29+
// If no object is passed to the BrowserWindow constructor we'll provide a default one
30+
options = JObject.Parse("{ width: 800, height: 600 }");
31+
}
2732

2833
JSBrowserWindowInstance instance = new JSBrowserWindowInstance(options);
2934
return instance.GetModule();
@@ -33,6 +38,8 @@ protected override JavaScriptValue Main(JavaScriptValue callee, bool isConstruct
3338
class JSBrowserWindowInstance : AbstractJSModule
3439
{
3540
private JToken options;
41+
// I don't really like putting this here, I think we should probably have a class that contains all our constants
42+
private const int defaultWindowWidth = 800, defaultWindowHeight = 600;
3643
private Dictionary<string, List<Tuple<JavaScriptValue, JavaScriptValue>>> listeners = new Dictionary<string, List<Tuple<JavaScriptValue, JavaScriptValue>>>();
3744

3845
public JSBrowserWindowInstance(JToken options) : base("BrowserWindowInstance")
@@ -49,11 +56,15 @@ public JSBrowserWindowInstance(JToken options) : base("BrowserWindowInstance")
4956
Int32.TryParse(options["width"].ToString(), out width);
5057
Int32.TryParse(options["height"].ToString(), out height);
5158

52-
if (width <= 0) width = 800;
53-
if (height <= 0) height = 600;
59+
if (width <= 0) width = defaultWindowWidth;
60+
if (height <= 0) height = defaultWindowHeight;
5461

5562
App.NewWindow(width, height);
5663
}
64+
else
65+
{
66+
App.NewWindow(defaultWindowWidth, defaultWindowHeight);
67+
}
5768
}
5869
protected JavaScriptValue LoadURL(JavaScriptValue callee, bool isConstructCall, JavaScriptValue[] arguments, ushort argumentCount, IntPtr callbackData)
5970
{
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
using ChakraHost.Hosting;
2+
using Newtonsoft.Json.Linq;
3+
using System;
4+
5+
namespace Electrino.JS
6+
{
7+
// Borrowed from: https://www.microsoft.com/reallifecode/2016/06/02/hybrid-apps-using-c-and-javascript-with-chakracore/
8+
public sealed class JTokenToJavaScriptValueConverter
9+
{
10+
private static readonly JTokenToJavaScriptValueConverter s_instance =
11+
new JTokenToJavaScriptValueConverter();
12+
13+
private JTokenToJavaScriptValueConverter() { }
14+
15+
public static JavaScriptValue Convert(JToken token)
16+
{
17+
return s_instance.Visit(token);
18+
}
19+
20+
private JavaScriptValue Visit(JToken token)
21+
{
22+
if (token == null)
23+
throw new ArgumentNullException(nameof(token));
24+
25+
switch (token.Type)
26+
{
27+
case JTokenType.Array:
28+
return VisitArray((JArray)token);
29+
case JTokenType.Boolean:
30+
return VisitBoolean((JValue)token);
31+
case JTokenType.Float:
32+
return VisitFloat((JValue)token);
33+
case JTokenType.Integer:
34+
return VisitInteger((JValue)token);
35+
case JTokenType.Null:
36+
return VisitNull(token);
37+
case JTokenType.Object:
38+
return VisitObject((JObject)token);
39+
case JTokenType.String:
40+
return VisitString((JValue)token);
41+
case JTokenType.Undefined:
42+
return VisitUndefined(token);
43+
default:
44+
throw new NotSupportedException();
45+
}
46+
}
47+
48+
private JavaScriptValue VisitArray(JArray token)
49+
{
50+
var n = token.Count;
51+
var array = AddRef(JavaScriptValue.CreateArray((uint)n));
52+
for (var i = 0; i < n; ++i)
53+
{
54+
var value = Visit(token[i]);
55+
array.SetIndexedProperty(JavaScriptValue.FromInt32(i), value);
56+
value.Release();
57+
}
58+
59+
return array;
60+
}
61+
62+
private JavaScriptValue VisitBoolean(JValue token)
63+
{
64+
return token.Value<bool>()
65+
? JavaScriptValue.True
66+
: JavaScriptValue.False;
67+
}
68+
69+
private JavaScriptValue VisitFloat(JValue token)
70+
{
71+
return AddRef(JavaScriptValue.FromDouble(token.Value<double>()));
72+
}
73+
74+
private JavaScriptValue VisitInteger(JValue token)
75+
{
76+
return AddRef(JavaScriptValue.FromDouble(token.Value<double>()));
77+
}
78+
79+
private JavaScriptValue VisitNull(JToken token)
80+
{
81+
return JavaScriptValue.Null;
82+
}
83+
84+
private JavaScriptValue VisitObject(JObject token)
85+
{
86+
var jsonObject = AddRef(JavaScriptValue.CreateObject());
87+
foreach (var entry in token)
88+
{
89+
var value = Visit(entry.Value);
90+
var propertyId = JavaScriptPropertyId.FromString(entry.Key);
91+
jsonObject.SetProperty(propertyId, value, true);
92+
value.Release();
93+
}
94+
95+
return jsonObject;
96+
}
97+
98+
private JavaScriptValue VisitString(JValue token)
99+
{
100+
return AddRef(JavaScriptValue.FromString(token.Value<string>()));
101+
}
102+
103+
private JavaScriptValue VisitUndefined(JToken token)
104+
{
105+
return JavaScriptValue.Undefined;
106+
}
107+
108+
private JavaScriptValue AddRef(JavaScriptValue value)
109+
{
110+
value.AddRef();
111+
return value;
112+
}
113+
}
114+
}

Electrino/win10/Electrino/JS/JavaScriptValueToJTokenConverter.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Electrino.JS
66
{
7+
// Borrowed from: https://www.microsoft.com/reallifecode/2016/06/02/hybrid-apps-using-c-and-javascript-with-chakracore/
78
public sealed class JavaScriptValueToJTokenConverter
89
{
910
private static readonly JToken s_true = new JValue(true);

Electrino/win10/Electrino/test-app/main.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@ var win = null;
1010

1111
console.log("hello world starting, app is: ", app);
1212

13-
function createWindow () {
14-
// Create the browser window.
13+
function createWindow() {
14+
// Create the browser window.
1515
win = new BrowserWindow({ width: 800, height: 600 });
1616

1717
console.log("createWindow", BrowserWindow, win);
18-
// and load the index.html of the app.
18+
// and load the index.html of the app.
1919
win.loadURL(url.format({
2020
pathname: path.join("/test-app", 'index.html'),
2121
protocol: 'ms-appx-web:',
2222
slashes: true
2323
}));
24-
// Emitted when the window is closed.
24+
// Emitted when the window is closed.
2525
win.on('closed', function () {
2626
// Dereference the window object, usually you would store windows
2727
// in an array if your app supports multi windows, this is the time

0 commit comments

Comments
 (0)