@nativescript/windows 0.1.0-alpha.76 → 0.1.0-alpha.78
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.
- package/framework/__PROJECT_NAME__/Directory.Build.targets +2 -2
- package/framework/dotnet-bridge/Bridge.BinaryDispatch.cs +17 -5
- package/framework/dotnet-bridge/Bridge.Dispatch.cs +40 -7
- package/framework/dotnet-bridge/Bridge.cs +132 -0
- package/framework/dotnet-bridge/DispatchTypes.cs +17 -4
- package/framework/libs/arm64/nativescript.dll +0 -0
- package/framework/libs/devtools/arm64/nativescript.dll +0 -0
- package/framework/libs/devtools/x64/nativescript.dll +0 -0
- package/framework/libs/x64/nativescript.dll +0 -0
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
easily overridden per-app or via MSBuild /p: properties. -->
|
|
7
7
|
|
|
8
8
|
<!-- Inline merge task: will merge App_Resources/Windows/Package.appxmanifest or Package.appxmanifest.partial.xml into the generated Package.appxmanifest -->
|
|
9
|
-
<UsingTask TaskName="MergeAppxManifest" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
|
9
|
+
<UsingTask TaskName="MergeAppxManifest" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" Condition="'$(MSBuildRuntimeType)' != 'Core'">
|
|
10
10
|
<ParameterGroup>
|
|
11
11
|
<SourceManifest ParameterType="System.String" Required="true" />
|
|
12
12
|
<TargetManifest ParameterType="System.String" Required="true" />
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
</Task>
|
|
86
86
|
</UsingTask>
|
|
87
87
|
|
|
88
|
-
<Target Name="MergeAppResourcesManifest" AfterTargets="ApplyManifestOverrides" Condition="Exists('$(MSBuildProjectDirectory)\Package.appxmanifest')">
|
|
88
|
+
<Target Name="MergeAppResourcesManifest" AfterTargets="ApplyManifestOverrides" Condition="Exists('$(MSBuildProjectDirectory)\Package.appxmanifest') and '$(MSBuildRuntimeType)' != 'Core'">
|
|
89
89
|
<PropertyGroup>
|
|
90
90
|
<_AppResourcesManifest>$(MSBuildProjectDirectory)\App_Resources\Windows\Package.appxmanifest</_AppResourcesManifest>
|
|
91
91
|
<!-- Allow CLI or callers to override the source manifest via MSBuild property 'AppResourcesManifestPath' -->
|
|
@@ -33,11 +33,23 @@ public static partial class Bridge
|
|
|
33
33
|
{
|
|
34
34
|
var op = r.ReadByte();
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
if (op == 0x04) // release
|
|
37
|
+
{
|
|
38
|
+
var handleToRemove = r.ReadI32();
|
|
39
|
+
s_handles.TryRemove(handleToRemove, out _);
|
|
40
|
+
if (s_nativePtrs.TryRemove(handleToRemove, out var nativePtr))
|
|
41
|
+
{
|
|
42
|
+
try
|
|
43
|
+
{
|
|
44
|
+
Marshal.Release(new IntPtr(nativePtr));
|
|
45
|
+
}
|
|
46
|
+
catch
|
|
47
|
+
{
|
|
48
|
+
// best-effort
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return DispatchResult.Void;
|
|
52
|
+
}
|
|
41
53
|
|
|
42
54
|
if (op == 0x05) // members by handle
|
|
43
55
|
{
|
|
@@ -18,11 +18,24 @@ public static partial class Bridge
|
|
|
18
18
|
{
|
|
19
19
|
var method = req.Method ?? throw new ArgumentException("Method is required");
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
if (method == "__release" && req.Handle.HasValue)
|
|
22
|
+
{
|
|
23
|
+
var id = req.Handle.Value;
|
|
24
|
+
s_handles.TryRemove(id, out _);
|
|
25
|
+
if (s_nativePtrs.TryRemove(id, out var nativePtr))
|
|
26
|
+
{
|
|
27
|
+
try
|
|
28
|
+
{
|
|
29
|
+
Marshal.Release(new IntPtr(nativePtr));
|
|
30
|
+
}
|
|
31
|
+
catch
|
|
32
|
+
{
|
|
33
|
+
// swallow - best-effort release
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return DispatchResult.Void;
|
|
38
|
+
}
|
|
26
39
|
|
|
27
40
|
object? target = null;
|
|
28
41
|
Type type;
|
|
@@ -244,8 +257,28 @@ public static partial class Bridge
|
|
|
244
257
|
catch { }
|
|
245
258
|
}
|
|
246
259
|
|
|
247
|
-
|
|
248
|
-
|
|
260
|
+
var id = Interlocked.Increment(ref s_nextHandle);
|
|
261
|
+
s_handles[id] = value;
|
|
262
|
+
|
|
263
|
+
// Try to obtain a canonical IUnknown pointer for COM/WinRT objects so the
|
|
264
|
+
// runtime can call native vtable methods directly. We addref via
|
|
265
|
+
// Marshal.GetIUnknownForObject and store the raw pointer; it will be
|
|
266
|
+
// released on __release.
|
|
267
|
+
try
|
|
268
|
+
{
|
|
269
|
+
if (value != null)
|
|
270
|
+
{
|
|
271
|
+
var p = Marshal.GetIUnknownForObject(value);
|
|
272
|
+
if (p != IntPtr.Zero)
|
|
273
|
+
{
|
|
274
|
+
s_nativePtrs[id] = p.ToInt64();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch
|
|
279
|
+
{
|
|
280
|
+
// Not a COM object or failed to obtain native pointer; ignore.
|
|
281
|
+
}
|
|
249
282
|
var typeName = t.FullName ?? t.Name;
|
|
250
283
|
return IsAwaitable(value, t)
|
|
251
284
|
? DispatchResult.TaskHandle(id, typeName)
|
|
@@ -48,9 +48,15 @@ public static partial class Bridge
|
|
|
48
48
|
s_propCache.Clear();
|
|
49
49
|
s_ctorCache.Clear();
|
|
50
50
|
s_handles.Clear();
|
|
51
|
+
s_nativePtrs.Clear();
|
|
51
52
|
s_nextHandle = 0;
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
// Optional mapping from exported handle id -> native IUnknown pointer (Int64)
|
|
56
|
+
// Populated when a managed object can yield a native COM pointer via
|
|
57
|
+
// Marshal.GetIUnknownForObject. Cleared and released on __release.
|
|
58
|
+
internal static readonly ConcurrentDictionary<int, long> s_nativePtrs = new();
|
|
59
|
+
|
|
54
60
|
// Returns a JSON object mapping top-level namespace roots (e.g. "NativeScript")
|
|
55
61
|
// to the assembly simple-name that most likely contains that namespace's types.
|
|
56
62
|
// Reuses s_assemblySearchDirs so plugin and NuGet assemblies are included.
|
|
@@ -326,6 +332,132 @@ public static partial class Bridge
|
|
|
326
332
|
return 0;
|
|
327
333
|
}
|
|
328
334
|
|
|
335
|
+
// Callback id registered by the runtime/JS that should receive unhandled
|
|
336
|
+
// managed exceptions and unobserved task exceptions.
|
|
337
|
+
private static int s_unhandledExceptionCallbackId = -1;
|
|
338
|
+
|
|
339
|
+
// Called from JS/Rust to request that managed unhandled exceptions be
|
|
340
|
+
// forwarded to the registered JS callback id. The callback id must have
|
|
341
|
+
// been created on the Rust side and point to a JS function stored in the
|
|
342
|
+
// runtime's `DOTNET_JS_CALLBACKS` map.
|
|
343
|
+
public static int RegisterUnhandledExceptionCallback(int callbackId)
|
|
344
|
+
{
|
|
345
|
+
s_unhandledExceptionCallbackId = callbackId;
|
|
346
|
+
|
|
347
|
+
// Subscribe once (idempotent).
|
|
348
|
+
try
|
|
349
|
+
{
|
|
350
|
+
AppDomain.CurrentDomain.UnhandledException -= OnAppDomainUnhandledException;
|
|
351
|
+
AppDomain.CurrentDomain.UnhandledException += OnAppDomainUnhandledException;
|
|
352
|
+
|
|
353
|
+
TaskScheduler.UnobservedTaskException -= OnUnobservedTaskException;
|
|
354
|
+
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
|
|
355
|
+
|
|
356
|
+
// Try to subscribe to Windows.CoreApplication.UnhandledErrorDetected if available
|
|
357
|
+
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
|
358
|
+
{
|
|
359
|
+
var coreAppType = asm.GetType("Windows.ApplicationModel.Core.CoreApplication");
|
|
360
|
+
if (coreAppType == null) continue;
|
|
361
|
+
var ev = coreAppType.GetEvent("UnhandledErrorDetected");
|
|
362
|
+
if (ev == null) continue;
|
|
363
|
+
try
|
|
364
|
+
{
|
|
365
|
+
var handlerType = ev.EventHandlerType;
|
|
366
|
+
var method = typeof(Bridge).GetMethod(nameof(CoreApplicationUnhandledErrorHandler), BindingFlags.NonPublic | BindingFlags.Static);
|
|
367
|
+
if (method != null)
|
|
368
|
+
{
|
|
369
|
+
var del = Delegate.CreateDelegate(handlerType, method);
|
|
370
|
+
ev.AddEventHandler(null, del);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
catch { }
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
catch { }
|
|
377
|
+
|
|
378
|
+
return 0;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Return a canonical native pointer (IUnknown / IInspectable) for an
|
|
382
|
+
// exported handle id. Returns 0 when no pointer is available. If a
|
|
383
|
+
// pointer isn't already cached in `s_nativePtrs`, attempt to obtain one
|
|
384
|
+
// via `Marshal.GetIUnknownForObject` and cache it for subsequent calls.
|
|
385
|
+
public static long GetNativePtrForHandle(int handleId)
|
|
386
|
+
{
|
|
387
|
+
if (handleId <= 0) return 0;
|
|
388
|
+
if (s_nativePtrs.TryGetValue(handleId, out var p)) return p;
|
|
389
|
+
|
|
390
|
+
if (!s_handles.TryGetValue(handleId, out var obj) || obj == null)
|
|
391
|
+
return 0;
|
|
392
|
+
|
|
393
|
+
try
|
|
394
|
+
{
|
|
395
|
+
var ip = Marshal.GetIUnknownForObject(obj);
|
|
396
|
+
if (ip != IntPtr.Zero)
|
|
397
|
+
{
|
|
398
|
+
var val = ip.ToInt64();
|
|
399
|
+
s_nativePtrs[handleId] = val;
|
|
400
|
+
return val;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
catch
|
|
404
|
+
{
|
|
405
|
+
// best-effort: not a COM object or failed to obtain native ptr
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return 0;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
private static void OnAppDomainUnhandledException(object? sender, UnhandledExceptionEventArgs e)
|
|
412
|
+
{
|
|
413
|
+
try
|
|
414
|
+
{
|
|
415
|
+
var ex = e.ExceptionObject as Exception;
|
|
416
|
+
var msg = ex?.ToString() ?? e.ExceptionObject?.ToString() ?? "(unknown)";
|
|
417
|
+
SendUnhandledToJs("unhandled", msg);
|
|
418
|
+
}
|
|
419
|
+
catch { }
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
private static void OnUnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
|
|
423
|
+
{
|
|
424
|
+
try
|
|
425
|
+
{
|
|
426
|
+
var msg = e.Exception?.ToString() ?? "(unobserved task exception)";
|
|
427
|
+
SendUnhandledToJs("unobservedTask", msg);
|
|
428
|
+
}
|
|
429
|
+
catch { }
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Fallback handler for platform-specific CoreApplication unhandled events.
|
|
433
|
+
private static void CoreApplicationUnhandledErrorHandler(object? sender, object? args)
|
|
434
|
+
{
|
|
435
|
+
try
|
|
436
|
+
{
|
|
437
|
+
var msg = args?.ToString() ?? "(core unhandled)";
|
|
438
|
+
SendUnhandledToJs("coreUnhandled", msg);
|
|
439
|
+
}
|
|
440
|
+
catch { }
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
private static unsafe void SendUnhandledToJs(string kind, string message)
|
|
444
|
+
{
|
|
445
|
+
try
|
|
446
|
+
{
|
|
447
|
+
if (s_jsInvoker == null || s_unhandledExceptionCallbackId <= 0) return;
|
|
448
|
+
var payload = JsonSerializer.Serialize(new { kind = kind, message = message });
|
|
449
|
+
var bytes = System.Text.Encoding.UTF8.GetBytes(payload);
|
|
450
|
+
fixed (byte* p = bytes)
|
|
451
|
+
{
|
|
452
|
+
byte* respPtr = null;
|
|
453
|
+
int respLen = 0;
|
|
454
|
+
s_jsInvoker(s_unhandledExceptionCallbackId, p, bytes.Length, &respPtr, &respLen);
|
|
455
|
+
if (respPtr != null && respLen > 0) Marshal.FreeHGlobal((IntPtr)respPtr);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
catch { }
|
|
459
|
+
}
|
|
460
|
+
|
|
329
461
|
[UnmanagedCallersOnly(EntryPoint = "Invoke",
|
|
330
462
|
CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
|
|
331
463
|
public static unsafe int Invoke(
|
|
@@ -115,10 +115,23 @@ internal readonly struct DispatchResult
|
|
|
115
115
|
break;
|
|
116
116
|
|
|
117
117
|
case DispatchKind.Handle:
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
118
|
+
w.WriteStartObject();
|
|
119
|
+
w.WriteNumber("__handle"u8, _handle);
|
|
120
|
+
w.WriteString("__type"u8, _typeName);
|
|
121
|
+
// If the bridge has a canonical native pointer for this handle,
|
|
122
|
+
// expose it as a hex string so the runtime can detect and use it.
|
|
123
|
+
if (Bridge.s_nativePtrs.TryGetValue(_handle, out var nativePtr))
|
|
124
|
+
{
|
|
125
|
+
try
|
|
126
|
+
{
|
|
127
|
+
w.WriteString("__native_ptr"u8, nativePtr.ToString("x"));
|
|
128
|
+
}
|
|
129
|
+
catch
|
|
130
|
+
{
|
|
131
|
+
// ignore formatting errors
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
w.WriteEndObject();
|
|
122
135
|
break;
|
|
123
136
|
|
|
124
137
|
case DispatchKind.TaskHandle:
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|