@nativescript/windows 0.1.0-alpha.50 → 0.1.0-alpha.52
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/dotnet-bridge/Bridge.Dispatch.cs +23 -14
- package/framework/dotnet-bridge/Bridge.cs +151 -0
- package/framework/dotnet-bridge/DispatchTypes.cs +27 -7
- 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
|
@@ -245,11 +245,20 @@ public static partial class Bridge
|
|
|
245
245
|
{
|
|
246
246
|
const BindingFlags inst = BindingFlags.Public | BindingFlags.Instance;
|
|
247
247
|
const BindingFlags stat = BindingFlags.Public | BindingFlags.Static;
|
|
248
|
+
|
|
249
|
+
var instProps = t.GetProperties(inst);
|
|
250
|
+
var statProps = t.GetProperties(stat);
|
|
251
|
+
|
|
248
252
|
return DispatchResult.Members(
|
|
249
|
-
t.GetMethods(inst).Where(m => !m.IsSpecialName).Select(m => m.Name).Distinct().ToArray(),
|
|
250
|
-
|
|
251
|
-
t.GetMethods(stat).Where(m => !m.IsSpecialName).Select(m => m.Name).Distinct().ToArray(),
|
|
252
|
-
|
|
253
|
+
methods: t.GetMethods(inst).Where(m => !m.IsSpecialName).Select(m => m.Name).Distinct().ToArray(),
|
|
254
|
+
props: instProps.Where(p => p.GetGetMethod() != null).Select(p => p.Name).Distinct().ToArray(),
|
|
255
|
+
staticMethods: t.GetMethods(stat).Where(m => !m.IsSpecialName).Select(m => m.Name).Distinct().ToArray(),
|
|
256
|
+
staticProps: statProps.Where(p => p.GetGetMethod() != null).Select(p => p.Name).Distinct().ToArray(),
|
|
257
|
+
readonlyProps: instProps.Where(p => p.GetGetMethod() != null && p.GetSetMethod() == null).Select(p => p.Name).Distinct().ToArray(),
|
|
258
|
+
readonlyStaticProps: statProps.Where(p => p.GetGetMethod() != null && p.GetSetMethod() == null).Select(p => p.Name).Distinct().ToArray(),
|
|
259
|
+
writeonlyProps: instProps.Where(p => p.GetGetMethod() == null && p.GetSetMethod() != null).Select(p => p.Name).Distinct().ToArray(),
|
|
260
|
+
writeonlyStaticProps: statProps.Where(p => p.GetGetMethod() == null && p.GetSetMethod() != null).Select(p => p.Name).Distinct().ToArray()
|
|
261
|
+
);
|
|
253
262
|
}
|
|
254
263
|
|
|
255
264
|
internal static Type? ResolveType(string? assemblyName, string? typeName)
|
|
@@ -288,12 +297,14 @@ public static partial class Bridge
|
|
|
288
297
|
// we catch and continue.
|
|
289
298
|
foreach (var ty in asm.GetTypes())
|
|
290
299
|
{
|
|
291
|
-
if (string.Equals(ty.FullName, typeName, StringComparison.Ordinal)
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
300
|
+
if (string.Equals(ty.FullName, typeName, StringComparison.Ordinal))
|
|
301
|
+
return ty;
|
|
302
|
+
// Short-name match only when input has no namespace prefix (e.g. "Stopwatch").
|
|
303
|
+
// Guarding on lastDot < 0 prevents matching unrelated types in other namespaces
|
|
304
|
+
// (e.g. "NativeScript.Widgets.FlexboxLayout" must not match a different
|
|
305
|
+
// FlexboxLayout that happens to live in another namespace).
|
|
306
|
+
if (lastDot < 0 && string.Equals(ty.Name, shortName, StringComparison.Ordinal))
|
|
295
307
|
return ty;
|
|
296
|
-
}
|
|
297
308
|
}
|
|
298
309
|
}
|
|
299
310
|
catch (ReflectionTypeLoadException) { }
|
|
@@ -315,12 +326,10 @@ public static partial class Bridge
|
|
|
315
326
|
{
|
|
316
327
|
foreach (var ty in asm.GetTypes())
|
|
317
328
|
{
|
|
318
|
-
if (string.Equals(ty.FullName, typeName, StringComparison.Ordinal)
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
{
|
|
329
|
+
if (string.Equals(ty.FullName, typeName, StringComparison.Ordinal))
|
|
330
|
+
return ty;
|
|
331
|
+
if (lastDot < 0 && string.Equals(ty.Name, shortName, StringComparison.Ordinal))
|
|
322
332
|
return ty;
|
|
323
|
-
}
|
|
324
333
|
}
|
|
325
334
|
}
|
|
326
335
|
catch (ReflectionTypeLoadException) { }
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
using System;
|
|
2
2
|
using System.Collections.Concurrent;
|
|
3
|
+
using System.Collections.Generic;
|
|
4
|
+
using System.IO;
|
|
5
|
+
using System.Linq;
|
|
3
6
|
using System.Reflection;
|
|
4
7
|
using System.Runtime.InteropServices;
|
|
8
|
+
using System.Runtime.Loader;
|
|
5
9
|
using System.Text.Json;
|
|
6
10
|
|
|
7
11
|
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("DotNetBridgeTests")]
|
|
@@ -24,6 +28,11 @@ public static partial class Bridge
|
|
|
24
28
|
private static readonly ConcurrentDictionary<MethodKey, DispatchEntry> s_methodCache = new();
|
|
25
29
|
private static readonly ConcurrentDictionary<PropKey, PropertyInfo?> s_propCache = new();
|
|
26
30
|
private static readonly ConcurrentDictionary<CtorKey, CtorEntry> s_ctorCache = new();
|
|
31
|
+
// Cache of attempted assembly loads (simple name -> Assembly or null if not found).
|
|
32
|
+
private static readonly ConcurrentDictionary<string, Assembly?> s_assemblyLoadCache
|
|
33
|
+
= new(StringComparer.OrdinalIgnoreCase);
|
|
34
|
+
// Directories to search for assemblies (initialized once in static ctor).
|
|
35
|
+
private static readonly string[] s_assemblySearchDirs;
|
|
27
36
|
|
|
28
37
|
private static readonly JsonSerializerOptions s_coerceOpts = new()
|
|
29
38
|
{
|
|
@@ -40,6 +49,148 @@ public static partial class Bridge
|
|
|
40
49
|
s_nextHandle = 0;
|
|
41
50
|
}
|
|
42
51
|
|
|
52
|
+
// Returns a JSON object mapping top-level namespace roots (e.g. "NativeScript")
|
|
53
|
+
// to the assembly simple-name that most likely contains that namespace's types.
|
|
54
|
+
// Reuses s_assemblySearchDirs so plugin and NuGet assemblies are included.
|
|
55
|
+
public static string GetNamespaceAssemblyMapJson()
|
|
56
|
+
{
|
|
57
|
+
var map = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
58
|
+
try
|
|
59
|
+
{
|
|
60
|
+
foreach (var dir in s_assemblySearchDirs.Where(Directory.Exists))
|
|
61
|
+
{
|
|
62
|
+
try
|
|
63
|
+
{
|
|
64
|
+
foreach (var file in Directory.EnumerateFiles(dir, "*.dll", SearchOption.TopDirectoryOnly))
|
|
65
|
+
{
|
|
66
|
+
try
|
|
67
|
+
{
|
|
68
|
+
var simple = Path.GetFileNameWithoutExtension(file);
|
|
69
|
+
if (string.IsNullOrEmpty(simple)) continue;
|
|
70
|
+
|
|
71
|
+
Assembly asm = AppDomain.CurrentDomain.GetAssemblies()
|
|
72
|
+
.FirstOrDefault(a => string.Equals(a.GetName().Name, simple, StringComparison.OrdinalIgnoreCase));
|
|
73
|
+
if (asm is null)
|
|
74
|
+
{
|
|
75
|
+
try { asm = AssemblyLoadContext.Default.LoadFromAssemblyPath(file); }
|
|
76
|
+
catch { continue; }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
Type[] types;
|
|
80
|
+
try { types = asm.GetExportedTypes(); }
|
|
81
|
+
catch { types = Array.Empty<Type>(); }
|
|
82
|
+
|
|
83
|
+
foreach (var t in types)
|
|
84
|
+
{
|
|
85
|
+
if (string.IsNullOrEmpty(t.Namespace)) continue;
|
|
86
|
+
var root = t.Namespace.Split('.')[0];
|
|
87
|
+
if (!map.ContainsKey(root)) map[root] = asm.GetName().Name;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch { }
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch { }
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch { }
|
|
97
|
+
try { return JsonSerializer.Serialize(map); } catch { return "{}"; }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Static ctor: initialize assembly search directories and register resolver.
|
|
101
|
+
static Bridge()
|
|
102
|
+
{
|
|
103
|
+
try
|
|
104
|
+
{
|
|
105
|
+
var baseDir = AppContext.BaseDirectory ?? AppDomain.CurrentDomain.BaseDirectory;
|
|
106
|
+
var dirs = new List<string> { baseDir };
|
|
107
|
+
|
|
108
|
+
// libs/ subtree relative to the bridge's own directory.
|
|
109
|
+
var libs = Path.Combine(baseDir, "libs");
|
|
110
|
+
if (Directory.Exists(libs))
|
|
111
|
+
{
|
|
112
|
+
dirs.Add(libs);
|
|
113
|
+
try { dirs.AddRange(Directory.GetDirectories(libs, "*", SearchOption.AllDirectories)); } catch { }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// The bridge DLL lives at dotnet-bridge/publish/ inside the app output root.
|
|
117
|
+
// Plugin assemblies (added via plugin.props) land at plugins/**/*.dll and NuGet
|
|
118
|
+
// assemblies land at the app output root itself — both outside the bridge subtree.
|
|
119
|
+
// Use the host process directory to reach them.
|
|
120
|
+
try
|
|
121
|
+
{
|
|
122
|
+
var processDir = Path.GetDirectoryName(
|
|
123
|
+
System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName);
|
|
124
|
+
if (!string.IsNullOrEmpty(processDir))
|
|
125
|
+
{
|
|
126
|
+
dirs.Add(processDir);
|
|
127
|
+
|
|
128
|
+
// plugins/ subtree: CLI-managed plugin DLLs live here.
|
|
129
|
+
var pluginsDir = Path.Combine(processDir, "plugins");
|
|
130
|
+
if (Directory.Exists(pluginsDir))
|
|
131
|
+
try { dirs.AddRange(Directory.GetDirectories(pluginsDir, "*", SearchOption.AllDirectories)); } catch { }
|
|
132
|
+
|
|
133
|
+
// libs/ relative to the app root (alternative convention).
|
|
134
|
+
var processLibs = Path.Combine(processDir, "libs");
|
|
135
|
+
if (Directory.Exists(processLibs))
|
|
136
|
+
try { dirs.AddRange(Directory.GetDirectories(processLibs, "*", SearchOption.AllDirectories)); } catch { }
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch { }
|
|
140
|
+
|
|
141
|
+
s_assemblySearchDirs = dirs.Where(d => !string.IsNullOrEmpty(d)).Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
|
|
142
|
+
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
|
|
143
|
+
}
|
|
144
|
+
catch
|
|
145
|
+
{
|
|
146
|
+
s_assemblySearchDirs = Array.Empty<string>();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private static Assembly? OnAssemblyResolve(object? sender, ResolveEventArgs args)
|
|
151
|
+
{
|
|
152
|
+
try
|
|
153
|
+
{
|
|
154
|
+
var requested = new AssemblyName(args.Name).Name;
|
|
155
|
+
if (string.IsNullOrEmpty(requested)) return null;
|
|
156
|
+
|
|
157
|
+
if (s_assemblyLoadCache.TryGetValue(requested, out var cached)) return cached;
|
|
158
|
+
|
|
159
|
+
// Check already-loaded assemblies first (avoid recursive Assembly.Load).
|
|
160
|
+
var loadedAsm = AppDomain.CurrentDomain.GetAssemblies()
|
|
161
|
+
.FirstOrDefault(a => string.Equals(a.GetName().Name, requested, StringComparison.OrdinalIgnoreCase));
|
|
162
|
+
if (loadedAsm is not null)
|
|
163
|
+
{
|
|
164
|
+
s_assemblyLoadCache[requested] = loadedAsm;
|
|
165
|
+
return loadedAsm;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Try to locate a matching dll in known search directories.
|
|
169
|
+
foreach (var dir in s_assemblySearchDirs)
|
|
170
|
+
{
|
|
171
|
+
try
|
|
172
|
+
{
|
|
173
|
+
var candidate = Path.Combine(dir, requested + ".dll");
|
|
174
|
+
if (File.Exists(candidate))
|
|
175
|
+
{
|
|
176
|
+
try
|
|
177
|
+
{
|
|
178
|
+
var asm = AssemblyLoadContext.Default.LoadFromAssemblyPath(candidate);
|
|
179
|
+
s_assemblyLoadCache[requested] = asm;
|
|
180
|
+
return asm;
|
|
181
|
+
}
|
|
182
|
+
catch { }
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
catch { }
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
s_assemblyLoadCache[requested] = null;
|
|
189
|
+
}
|
|
190
|
+
catch { }
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
|
|
43
194
|
[UnmanagedCallersOnly(EntryPoint = "RegisterJsCallback",
|
|
44
195
|
CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
|
|
45
196
|
public static unsafe int RegisterJsCallback(
|
|
@@ -71,14 +71,22 @@ internal readonly struct DispatchResult
|
|
|
71
71
|
private readonly string[]? _properties;
|
|
72
72
|
private readonly string[]? _staticMethods;
|
|
73
73
|
private readonly string[]? _staticProperties;
|
|
74
|
+
private readonly string[]? _readonlyProperties;
|
|
75
|
+
private readonly string[]? _readonlyStaticProperties;
|
|
76
|
+
private readonly string[]? _writeonlyProperties;
|
|
77
|
+
private readonly string[]? _writeonlyStaticProperties;
|
|
74
78
|
|
|
75
79
|
private DispatchResult(DispatchKind kind, object? value, Type? type, int handle,
|
|
76
80
|
string? typeName, string[]? methods, string[]? props,
|
|
77
|
-
string[]? staticMethods, string[]? staticProps
|
|
81
|
+
string[]? staticMethods, string[]? staticProps,
|
|
82
|
+
string[]? readonlyProps = null, string[]? readonlyStaticProps = null,
|
|
83
|
+
string[]? writeonlyProps = null, string[]? writeonlyStaticProps = null)
|
|
78
84
|
{
|
|
79
85
|
_kind = kind; _value = value; _type = type; _handle = handle;
|
|
80
86
|
_typeName = typeName; _methods = methods; _properties = props;
|
|
81
87
|
_staticMethods = staticMethods; _staticProperties = staticProps;
|
|
88
|
+
_readonlyProperties = readonlyProps; _readonlyStaticProperties = readonlyStaticProps;
|
|
89
|
+
_writeonlyProperties = writeonlyProps; _writeonlyStaticProperties = writeonlyStaticProps;
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
public static DispatchResult Primitive(object value, Type type)
|
|
@@ -91,8 +99,12 @@ internal readonly struct DispatchResult
|
|
|
91
99
|
=> new(DispatchKind.Collection, items, null, 0, null, null, null, null, null);
|
|
92
100
|
|
|
93
101
|
public static DispatchResult Members(
|
|
94
|
-
string[] methods, string[] props, string[] staticMethods, string[] staticProps
|
|
95
|
-
|
|
102
|
+
string[] methods, string[] props, string[] staticMethods, string[] staticProps,
|
|
103
|
+
string[] readonlyProps, string[] readonlyStaticProps,
|
|
104
|
+
string[] writeonlyProps, string[] writeonlyStaticProps)
|
|
105
|
+
=> new(DispatchKind.Members, null, null, 0, null,
|
|
106
|
+
methods, props, staticMethods, staticProps,
|
|
107
|
+
readonlyProps, readonlyStaticProps, writeonlyProps, writeonlyStaticProps);
|
|
96
108
|
|
|
97
109
|
internal int HandleId() => _handle;
|
|
98
110
|
|
|
@@ -126,10 +138,14 @@ internal readonly struct DispatchResult
|
|
|
126
138
|
|
|
127
139
|
case DispatchKind.Members:
|
|
128
140
|
w.WriteStartObject();
|
|
129
|
-
WriteStringArray(w, "methods"u8,
|
|
130
|
-
WriteStringArray(w, "properties"u8,
|
|
131
|
-
WriteStringArray(w, "staticMethods"u8,
|
|
132
|
-
WriteStringArray(w, "staticProperties"u8,
|
|
141
|
+
WriteStringArray(w, "methods"u8, _methods!);
|
|
142
|
+
WriteStringArray(w, "properties"u8, _properties!);
|
|
143
|
+
WriteStringArray(w, "staticMethods"u8, _staticMethods!);
|
|
144
|
+
WriteStringArray(w, "staticProperties"u8, _staticProperties!);
|
|
145
|
+
WriteStringArray(w, "readonlyProperties"u8, _readonlyProperties!);
|
|
146
|
+
WriteStringArray(w, "readonlyStaticProperties"u8, _readonlyStaticProperties!);
|
|
147
|
+
WriteStringArray(w, "writeonlyProperties"u8, _writeonlyProperties!);
|
|
148
|
+
WriteStringArray(w, "writeonlyStaticProperties"u8,_writeonlyStaticProperties!);
|
|
133
149
|
w.WriteEndObject();
|
|
134
150
|
break;
|
|
135
151
|
}
|
|
@@ -185,6 +201,10 @@ internal readonly struct DispatchResult
|
|
|
185
201
|
WriteStringArrayBin(ref w, _properties!);
|
|
186
202
|
WriteStringArrayBin(ref w, _staticMethods!);
|
|
187
203
|
WriteStringArrayBin(ref w, _staticProperties!);
|
|
204
|
+
WriteStringArrayBin(ref w, _readonlyProperties!);
|
|
205
|
+
WriteStringArrayBin(ref w, _readonlyStaticProperties!);
|
|
206
|
+
WriteStringArrayBin(ref w, _writeonlyProperties!);
|
|
207
|
+
WriteStringArrayBin(ref w, _writeonlyStaticProperties!);
|
|
188
208
|
break;
|
|
189
209
|
}
|
|
190
210
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|