@devscholar/node-ps1-dotnet 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/EnsureBom.ps1 +27 -0
  2. package/LICENSE.md +22 -0
  3. package/README.md +65 -0
  4. package/examples/console/await-delay/await-delay.ts +14 -0
  5. package/examples/console/console-input/console-input.ts +18 -0
  6. package/examples/winforms/counter/counter.ts +47 -0
  7. package/examples/winforms/drag-box/drag-box.ts +62 -0
  8. package/examples/wpf/counter/counter.ts +55 -0
  9. package/examples/wpf/drag-box/drag-box.ts +84 -0
  10. package/examples/wpf/webview2-browser/WebView2Libs/Microsoft.Web.WebView2.Core.dll +0 -0
  11. package/examples/wpf/webview2-browser/WebView2Libs/Microsoft.Web.WebView2.Core.dll.backup +0 -0
  12. package/examples/wpf/webview2-browser/WebView2Libs/Microsoft.Web.WebView2.Wpf.dll +0 -0
  13. package/examples/wpf/webview2-browser/WebView2Libs/Microsoft.Web.WebView2.Wpf.dll.backup +0 -0
  14. package/examples/wpf/webview2-browser/WebView2Libs/WebView2License.txt +27 -0
  15. package/examples/wpf/webview2-browser/counter.html +31 -0
  16. package/examples/wpf/webview2-browser/webview2-browser.ts +90 -0
  17. package/package.json +19 -0
  18. package/scripts/PsBridge/BridgeState.cs +39 -0
  19. package/scripts/PsBridge/Protocol.cs +222 -0
  20. package/scripts/PsBridge/PsBridge.psd1 +10 -0
  21. package/scripts/PsBridge/PsBridge.psm1 +22 -0
  22. package/scripts/PsBridge/PsHost.cs +393 -0
  23. package/scripts/PsBridge/PsHostEntry.cs +23 -0
  24. package/scripts/PsBridge/Reflection.cs +830 -0
  25. package/scripts/PsHost.ps1 +11 -0
  26. package/src/index.ts +510 -0
  27. package/src/ipc.ts +182 -0
  28. package/src/types.ts +21 -0
  29. package/src/utils.ts +13 -0
  30. package/start.js +67 -0
  31. package/tsconfig.json +14 -0
@@ -0,0 +1,222 @@
1
+
2
+ // scripts/PsBridge/Protocol.cs
3
+ using System;
4
+ using System.Collections.Generic;
5
+ using System.Reflection;
6
+ using System.Runtime.InteropServices;
7
+ using System.Text;
8
+ using System.Threading.Tasks;
9
+
10
+ public static class Protocol
11
+ {
12
+ public static Dictionary<string, object> ConvertToProtocol(object inputObject)
13
+ {
14
+ if (inputObject == null)
15
+ {
16
+ return new Dictionary<string, object> { { "type", "null" } };
17
+ }
18
+
19
+ if (inputObject is bool || inputObject is string)
20
+ {
21
+ return new Dictionary<string, object> { { "type", "primitive" }, { "value", inputObject } };
22
+ }
23
+
24
+ if (inputObject.GetType().IsPrimitive)
25
+ {
26
+ var val = inputObject;
27
+ if (val is double || val is float)
28
+ {
29
+ double dVal = Convert.ToDouble(val);
30
+ if (double.IsNaN(dVal) || double.IsInfinity(dVal))
31
+ {
32
+ val = null;
33
+ }
34
+ }
35
+ return new Dictionary<string, object> { { "type", "primitive" }, { "value", val } };
36
+ }
37
+
38
+ if (inputObject is Task)
39
+ {
40
+ var refId = Guid.NewGuid().ToString();
41
+ BridgeState.ObjectStore[refId] = inputObject;
42
+ return new Dictionary<string, object>
43
+ {
44
+ { "type", "task" },
45
+ { "id", refId },
46
+ { "netType", inputObject.GetType().FullName }
47
+ };
48
+ }
49
+
50
+ if (inputObject is Array)
51
+ {
52
+ var arr = (Array)inputObject;
53
+ var arrResult = new List<Dictionary<string, object>>();
54
+ foreach (var item in arr)
55
+ {
56
+ arrResult.Add(ConvertToProtocol(item));
57
+ }
58
+ return new Dictionary<string, object> { { "type", "array" }, { "value", arrResult } };
59
+ }
60
+
61
+ var objRefId = Guid.NewGuid().ToString();
62
+ BridgeState.ObjectStore[objRefId] = inputObject;
63
+
64
+ return new Dictionary<string, object>
65
+ {
66
+ { "type", "ref" },
67
+ { "id", objRefId },
68
+ { "netType", inputObject.GetType().FullName }
69
+ };
70
+ }
71
+
72
+ public static object[] ResolveArgs(object argsObj)
73
+ {
74
+ var realArgs = new List<object>();
75
+
76
+ IEnumerable<object> cmdArgs = null;
77
+ if (argsObj is object[])
78
+ {
79
+ cmdArgs = ((object[])argsObj);
80
+ }
81
+ else if (argsObj is List<object>)
82
+ {
83
+ cmdArgs = (List<object>)argsObj;
84
+ }
85
+
86
+ if (cmdArgs != null)
87
+ {
88
+ foreach (var arg in cmdArgs)
89
+ {
90
+ var dict = arg as Dictionary<string, object>;
91
+ if (dict != null && dict.ContainsKey("__ref"))
92
+ {
93
+ realArgs.Add(BridgeState.ObjectStore[dict["__ref"].ToString()]);
94
+ }
95
+ else if (dict != null && dict.ContainsKey("type") && dict["type"].ToString() == "callback")
96
+ {
97
+ var cbId = dict["callbackId"].ToString();
98
+
99
+ Func<object, object, object, object, object> callback = (p1, p2, p3, p4) =>
100
+ {
101
+ var netCallbackArgs = new object[] { p1, p2, p3, p4 };
102
+
103
+ var validProtoArgs = new List<Dictionary<string, object>>();
104
+ foreach (var a in netCallbackArgs)
105
+ {
106
+ if (a != null)
107
+ {
108
+ validProtoArgs.Add(ConvertToProtocol(a));
109
+ }
110
+ }
111
+
112
+ var msg = new Dictionary<string, object>
113
+ {
114
+ { "type", "event" },
115
+ { "callbackId", cbId },
116
+ { "args", validProtoArgs }
117
+ };
118
+
119
+ var json = SimpleJson.Serialize(msg);
120
+
121
+ BridgeState.Writer.WriteLine(json);
122
+
123
+ object result = null;
124
+ try
125
+ {
126
+ if (PsHost.ProcessNestedCommands != null)
127
+ {
128
+ result = PsHost.ProcessNestedCommands();
129
+ }
130
+ }
131
+ catch { }
132
+
133
+ return result;
134
+ };
135
+
136
+ realArgs.Add(callback);
137
+ }
138
+ else
139
+ {
140
+ realArgs.Add(arg);
141
+ }
142
+ }
143
+ }
144
+ return realArgs.ToArray();
145
+ }
146
+
147
+ public static void RemoveBridgeObject(string id)
148
+ {
149
+ BridgeState.ObjectStore.Remove(id);
150
+ }
151
+ }
152
+
153
+ public static class SimpleJson
154
+ {
155
+ public static string Serialize(object obj)
156
+ {
157
+ if (obj == null) return "null";
158
+
159
+ if (obj is Dictionary<string, object>)
160
+ {
161
+ var dict = (Dictionary<string, object>)obj;
162
+ var parts = new List<string>();
163
+ foreach (var kvp in dict)
164
+ {
165
+ parts.Add(string.Format("\"{0}\":{1}", EscapeString(kvp.Key), Serialize(kvp.Value)));
166
+ }
167
+ return "{" + string.Join(",", parts.ToArray()) + "}";
168
+ }
169
+
170
+ if (obj is List<Dictionary<string, object>>)
171
+ {
172
+ var list = (List<Dictionary<string, object>>)obj;
173
+ var parts = new List<string>();
174
+ foreach (var item in list)
175
+ {
176
+ parts.Add(Serialize(item));
177
+ }
178
+ return "[" + string.Join(",", parts.ToArray()) + "]";
179
+ }
180
+
181
+ if (obj is string)
182
+ {
183
+ return "\"" + EscapeString((string)obj) + "\"";
184
+ }
185
+
186
+ if (obj is bool)
187
+ {
188
+ return (bool)obj ? "true" : "false";
189
+ }
190
+
191
+ if (obj == null)
192
+ {
193
+ return "null";
194
+ }
195
+
196
+ if (obj.GetType().IsPrimitive || obj is decimal)
197
+ {
198
+ return obj.ToString();
199
+ }
200
+
201
+ return "\"" + EscapeString(obj.ToString()) + "\"";
202
+ }
203
+
204
+ private static string EscapeString(string s)
205
+ {
206
+ if (s == null) return "";
207
+ var sb = new StringBuilder();
208
+ foreach (var c in s)
209
+ {
210
+ switch (c)
211
+ {
212
+ case '\\': sb.Append("\\\\"); break;
213
+ case '"': sb.Append("\\\""); break;
214
+ case '\n': sb.Append("\\n"); break;
215
+ case '\r': sb.Append("\\r"); break;
216
+ case '\t': sb.Append("\\t"); break;
217
+ default: sb.Append(c); break;
218
+ }
219
+ }
220
+ return sb.ToString();
221
+ }
222
+ }
@@ -0,0 +1,10 @@
1
+ 
2
+ # scripts/PsBridge/PsBridge.psd1
3
+ @{
4
+ ModuleVersion = '1.0.0'
5
+ RootModule = 'PsBridge.psm1'
6
+ FunctionsToExport = '*'
7
+ CmdletsToExport = '*'
8
+ VariablesToExport = '*'
9
+ AliasesToExport = '*'
10
+ }
@@ -0,0 +1,22 @@
1
+ # scripts/PsBridge/PsBridge.psm1
2
+ $scriptDir = Split-Path $MyInvocation.MyCommand.Path
3
+
4
+ $csFiles = @(
5
+ "$scriptDir\BridgeState.cs",
6
+ "$scriptDir\Protocol.cs",
7
+ "$scriptDir\Reflection.cs",
8
+ "$scriptDir\PsHost.cs",
9
+ "$scriptDir\PsHostEntry.cs"
10
+ )
11
+
12
+ $referencedAssemblies = @(
13
+ 'System.dll',
14
+ 'System.Core.dll',
15
+ 'System.Windows.Forms.dll',
16
+ 'System.Drawing.dll',
17
+ 'System.Runtime.InteropServices.dll'
18
+ )
19
+
20
+ Add-Type -Path $csFiles -ReferencedAssemblies $referencedAssemblies
21
+
22
+ Export-ModuleMember -Function ConvertTo-Protocol, Resolve-Args, Invoke-ReflectionLogic, Remove-BridgeObject -Variable BridgeState
@@ -0,0 +1,393 @@
1
+ // scripts/PsBridge/PsHost.cs
2
+ using System;
3
+ using System.Collections.Concurrent;
4
+ using System.Collections.Generic;
5
+ using System.Globalization;
6
+ using System.IO;
7
+ using System.IO.Pipes;
8
+ using System.Text;
9
+ using System.Threading;
10
+
11
+ public static class PsHost
12
+ {
13
+ public static Func<object> ProcessNestedCommands { get; set; }
14
+
15
+ public static BlockingCollection<Dictionary<string, object>> CommandQueue = new BlockingCollection<Dictionary<string, object>>();
16
+ public static BlockingCollection<Dictionary<string, object>> ReplyQueue = new BlockingCollection<Dictionary<string, object>>();
17
+ public static SynchronizationContext MainSyncContext { get; set; }
18
+
19
+ public static object RunProcessNestedCommands()
20
+ {
21
+ var queues = new BlockingCollection<Dictionary<string, object>>[] { ReplyQueue, CommandQueue };
22
+
23
+ while (BridgeState.PipeServer != null && BridgeState.PipeServer.IsConnected)
24
+ {
25
+ Dictionary<string, object> item;
26
+ int index = BlockingCollection<Dictionary<string, object>>.TakeFromAny(queues, out item);
27
+
28
+ if (index == 0)
29
+ {
30
+ if (item != null && item.ContainsKey("result"))
31
+ {
32
+ return item["result"];
33
+ }
34
+ return null;
35
+ }
36
+ else if (index == 1)
37
+ {
38
+ if (item != null)
39
+ {
40
+ ExecuteCommand(item);
41
+ }
42
+ }
43
+ }
44
+ return null;
45
+ }
46
+
47
+ private static void UpdateSyncContext()
48
+ {
49
+ if (SynchronizationContext.Current != null && MainSyncContext != SynchronizationContext.Current)
50
+ {
51
+ MainSyncContext = SynchronizationContext.Current;
52
+ }
53
+ }
54
+
55
+ public static void ExecuteCommand(Dictionary<string, object> cmd)
56
+ {
57
+ if (cmd == null) return;
58
+
59
+ try
60
+ {
61
+ var result = Reflection.InvokeReflectionLogic(cmd);
62
+ UpdateSyncContext();
63
+
64
+ var json = SimpleJson.Serialize(result);
65
+ lock (BridgeState.Writer)
66
+ {
67
+ BridgeState.Writer.WriteLine(json);
68
+ }
69
+ }
70
+ catch (Exception ex)
71
+ {
72
+ UpdateSyncContext();
73
+ var errMsg = ex.InnerException != null ? ex.InnerException.Message : ex.Message;
74
+ var errJson = SimpleJson.Serialize(new Dictionary<string, object>
75
+ {
76
+ { "type", "error" },
77
+ { "message", errMsg.Replace("\"", "'") }
78
+ });
79
+ lock (BridgeState.Writer)
80
+ {
81
+ BridgeState.Writer.WriteLine(errJson);
82
+ }
83
+ }
84
+ }
85
+
86
+ public static void DrainCommandQueue(object state)
87
+ {
88
+ Dictionary<string, object> cmd;
89
+ while (CommandQueue.TryTake(out cmd))
90
+ {
91
+ UpdateSyncContext();
92
+ ExecuteCommand(cmd);
93
+ }
94
+ }
95
+
96
+ public static void StartServer()
97
+ {
98
+ // Key change: Changed PipeOptions.None to PipeOptions.Asynchronous
99
+ // This allows Windows to perform concurrent overlapped I/O on the handle, so reader thread suspension will never block main thread writes!
100
+ BridgeState.PipeServer = new NamedPipeServerStream(
101
+ BridgeState.PipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
102
+
103
+ BridgeState.PipeServer.WaitForConnection();
104
+ BridgeState.Reader = new StreamReader(BridgeState.PipeServer);
105
+ BridgeState.Writer = new StreamWriter(BridgeState.PipeServer);
106
+ BridgeState.Writer.AutoFlush = true;
107
+
108
+ var readerThread = new Thread(() =>
109
+ {
110
+ try
111
+ {
112
+ while (BridgeState.PipeServer.IsConnected)
113
+ {
114
+ var line = BridgeState.Reader.ReadLine();
115
+ if (line == null) break;
116
+
117
+ var msg = SimpleJsonDeserializer.Deserialize(line) as Dictionary<string, object>;
118
+ if (msg == null) continue;
119
+
120
+ if (msg.ContainsKey("type") && msg["type"].ToString() == "reply")
121
+ {
122
+ ReplyQueue.Add(msg);
123
+ }
124
+ else
125
+ {
126
+ CommandQueue.Add(msg);
127
+ if (MainSyncContext != null)
128
+ {
129
+ MainSyncContext.Post(DrainCommandQueue, null);
130
+ }
131
+ }
132
+ }
133
+ }
134
+ catch { }
135
+ finally
136
+ {
137
+ CommandQueue.CompleteAdding();
138
+ ReplyQueue.CompleteAdding();
139
+ }
140
+ });
141
+ readerThread.IsBackground = true;
142
+ readerThread.Start();
143
+
144
+ try
145
+ {
146
+ foreach (var cmd in CommandQueue.GetConsumingEnumerable())
147
+ {
148
+ UpdateSyncContext();
149
+ ExecuteCommand(cmd);
150
+ }
151
+ }
152
+ catch { }
153
+
154
+ Environment.Exit(0);
155
+ }
156
+ }
157
+
158
+ // SimpleJsonDeserializer requires no changes, it works as-is...
159
+ public static class SimpleJsonDeserializer
160
+ {
161
+ private static int _index;
162
+ private static string _json;
163
+
164
+ public static object Deserialize(string json)
165
+ {
166
+ _json = json;
167
+ _index = 0;
168
+ return ParseValue();
169
+ }
170
+
171
+ private static void SkipWhitespace()
172
+ {
173
+ while (_index < _json.Length && char.IsWhiteSpace(_json[_index]))
174
+ {
175
+ _index++;
176
+ }
177
+ }
178
+
179
+ private static object ParseValue()
180
+ {
181
+ SkipWhitespace();
182
+
183
+ if (_index >= _json.Length) return null;
184
+
185
+ var c = _json[_index];
186
+
187
+ if (c == 'n')
188
+ {
189
+ _index += 4;
190
+ return null;
191
+ }
192
+
193
+ if (c == 't')
194
+ {
195
+ _index += 4;
196
+ return true;
197
+ }
198
+
199
+ if (c == 'f')
200
+ {
201
+ _index += 5;
202
+ return false;
203
+ }
204
+
205
+ if (c == '"')
206
+ {
207
+ return ParseString();
208
+ }
209
+
210
+ if (c == '{')
211
+ {
212
+ return ParseObject();
213
+ }
214
+
215
+ if (c == '[')
216
+ {
217
+ return ParseArray();
218
+ }
219
+
220
+ if (c == '-' || char.IsDigit(c))
221
+ {
222
+ return ParseNumber();
223
+ }
224
+
225
+ return null;
226
+ }
227
+
228
+ private static string ParseString()
229
+ {
230
+ _index++;
231
+ var start = _index;
232
+ var result = new StringBuilder();
233
+
234
+ while (_index < _json.Length && _json[_index] != '"')
235
+ {
236
+ if (_json[_index] == '\\')
237
+ {
238
+ result.Append(_json.Substring(start, _index - start));
239
+ _index++;
240
+ if (_index < _json.Length)
241
+ {
242
+ var escaped = _json[_index];
243
+ switch (escaped)
244
+ {
245
+ case '"': result.Append('"'); break;
246
+ case '\\': result.Append('\\'); break;
247
+ case 'n': result.Append('\n'); break;
248
+ case 'r': result.Append('\r'); break;
249
+ case 't': result.Append('\t'); break;
250
+ default: result.Append(escaped); break;
251
+ }
252
+ _index++;
253
+ start = _index;
254
+ }
255
+ }
256
+ else
257
+ {
258
+ _index++;
259
+ }
260
+ }
261
+
262
+ result.Append(_json.Substring(start, _index - start));
263
+ _index++;
264
+
265
+ return result.ToString();
266
+ }
267
+
268
+ private static object ParseNumber()
269
+ {
270
+ var start = _index;
271
+
272
+ if (_json[_index] == '-') _index++;
273
+
274
+ while (_index < _json.Length && char.IsDigit(_json[_index]))
275
+ {
276
+ _index++;
277
+ }
278
+
279
+ var isDouble = false;
280
+ if (_index < _json.Length && _json[_index] == '.')
281
+ {
282
+ isDouble = true;
283
+ _index++;
284
+ while (_index < _json.Length && char.IsDigit(_json[_index]))
285
+ {
286
+ _index++;
287
+ }
288
+ }
289
+
290
+ if (_index < _json.Length && (_json[_index] == 'e' || _json[_index] == 'E'))
291
+ {
292
+ isDouble = true;
293
+ _index++;
294
+ if (_index < _json.Length && (_json[_index] == '+' || _json[_index] == '-'))
295
+ {
296
+ _index++;
297
+ }
298
+ while (_index < _json.Length && char.IsDigit(_json[_index]))
299
+ {
300
+ _index++;
301
+ }
302
+ }
303
+
304
+ var numStr = _json.Substring(start, _index - start);
305
+
306
+ if (isDouble)
307
+ {
308
+ return double.Parse(numStr, CultureInfo.InvariantCulture);
309
+ }
310
+ else
311
+ {
312
+ return long.Parse(numStr);
313
+ }
314
+ }
315
+
316
+ private static Dictionary<string, object> ParseObject()
317
+ {
318
+ var result = new Dictionary<string, object>();
319
+ _index++;
320
+
321
+ SkipWhitespace();
322
+
323
+ if (_index < _json.Length && _json[_index] == '}')
324
+ {
325
+ _index++;
326
+ return result;
327
+ }
328
+
329
+ while (_index < _json.Length)
330
+ {
331
+ SkipWhitespace();
332
+
333
+ var key = ParseString();
334
+
335
+ SkipWhitespace();
336
+ _index++;
337
+
338
+ var value = ParseValue();
339
+
340
+ result[key] = value;
341
+
342
+ SkipWhitespace();
343
+
344
+ if (_index < _json.Length && _json[_index] == '}')
345
+ {
346
+ _index++;
347
+ break;
348
+ }
349
+
350
+ if (_index < _json.Length && _json[_index] == ',')
351
+ {
352
+ _index++;
353
+ }
354
+ }
355
+
356
+ return result;
357
+ }
358
+
359
+ private static List<object> ParseArray()
360
+ {
361
+ var result = new List<object>();
362
+ _index++;
363
+
364
+ SkipWhitespace();
365
+
366
+ if (_index < _json.Length && _json[_index] == ']')
367
+ {
368
+ _index++;
369
+ return result;
370
+ }
371
+
372
+ while (_index < _json.Length)
373
+ {
374
+ var value = ParseValue();
375
+ result.Add(value);
376
+
377
+ SkipWhitespace();
378
+
379
+ if (_index < _json.Length && _json[_index] == ']')
380
+ {
381
+ _index++;
382
+ break;
383
+ }
384
+
385
+ if (_index < _json.Length && _json[_index] == ',')
386
+ {
387
+ _index++;
388
+ }
389
+ }
390
+
391
+ return result;
392
+ }
393
+ }
@@ -0,0 +1,23 @@
1
+ // scripts/PsBridge/PsHostEntry.cs
2
+ using System;
3
+
4
+ public static class PsHostEntry
5
+ {
6
+ public static void Run(string pipeName)
7
+ {
8
+ BridgeState.PipeName = pipeName;
9
+ PsHost.ProcessNestedCommands = PsHost.RunProcessNestedCommands;
10
+
11
+ try
12
+ {
13
+ PsHost.StartServer();
14
+ }
15
+ finally
16
+ {
17
+ if (BridgeState.PipeServer != null)
18
+ {
19
+ BridgeState.PipeServer.Dispose();
20
+ }
21
+ }
22
+ }
23
+ }