@nativescript/windows-hermes 0.1.0-next.2026-08-03-30819078286 → 1.0.0-beta.7
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__/App.xaml.cs +3 -2
- package/framework/__PROJECT_NAME__/CrashDiagnostics.cs +3 -3
- package/framework/__PROJECT_NAME__/RuntimeHost.cs +149 -24
- package/framework/__PROJECT_NAME__/__PROJECT_NAME__.csproj +35 -41
- package/framework/dotnet-bridge/BinaryProtocol.cs +18 -0
- package/framework/dotnet-bridge/Bridge.BinaryDispatch.cs +83 -8
- package/framework/dotnet-bridge/Bridge.Dispatch.cs +40 -35
- package/framework/dotnet-bridge/Bridge.JsDelegate.cs +115 -59
- package/framework/dotnet-bridge/Bridge.Proxy.cs +158 -230
- package/framework/dotnet-bridge/Bridge.TaskHelper.cs +2 -1
- package/framework/dotnet-bridge/Bridge.cs +45 -5
- package/framework/dotnet-bridge/DotNetBridge.csproj +8 -0
- package/framework/libs/x64/nativescript.dll +0 -0
- package/framework/tools/ManifestMerger/ManifestMerger.dll +0 -0
- package/framework/tools/ManifestMerger/ManifestMerger.pdb +0 -0
- package/framework/tools/dotnet-tool-x64.exe +0 -0
- package/framework/tools/dotnet-tool.exe +0 -0
- package/framework/tools/dotnet-typings-gen/dotnet-typings-gen.dll +0 -0
- package/framework/tools/dotnet-typings-gen/dotnet-typings-gen.exe +0 -0
- package/framework/tools/dotnet-typings-gen/dotnet-typings-gen.pdb +0 -0
- package/framework/tools/nsbundle_pack-x64.exe +0 -0
- package/framework/tools/nsbundle_pack.exe +0 -0
- package/framework/tools/typings-generator-x64.exe +0 -0
- package/framework/tools/typings-generator.exe +0 -0
- package/package.json +1 -1
- package/framework/tools/sbg-arm64.exe +0 -0
- package/framework/tools/sbg-x64.exe +0 -0
- package/framework/tools/sbg.exe +0 -0
|
@@ -57,7 +57,7 @@ namespace __PROJECT_NAME__
|
|
|
57
57
|
try
|
|
58
58
|
{
|
|
59
59
|
var panicLogPath = System.IO.Path.Combine(
|
|
60
|
-
|
|
60
|
+
RuntimeHost.LocalFolderPath, "nativescript-panic.log");
|
|
61
61
|
if (System.IO.File.Exists(panicLogPath))
|
|
62
62
|
{
|
|
63
63
|
var content = System.IO.File.ReadAllText(panicLogPath);
|
|
@@ -121,7 +121,8 @@ namespace __PROJECT_NAME__
|
|
|
121
121
|
{
|
|
122
122
|
StopPump();
|
|
123
123
|
_runtimeHost.NotifyAppEvent((int)AppEventKind.Exit, null);
|
|
124
|
-
ApplicationData.Current.LocalSettings.Values[LastLaunchArgsKey] = string.Empty;
|
|
124
|
+
try { ApplicationData.Current.LocalSettings.Values[LastLaunchArgsKey] = string.Empty; }
|
|
125
|
+
catch (InvalidOperationException) { } // unpackaged: no ApplicationData
|
|
125
126
|
_runtimeHost.Dispose();
|
|
126
127
|
}
|
|
127
128
|
|
|
@@ -101,7 +101,7 @@ namespace __PROJECT_NAME__
|
|
|
101
101
|
// Include panic log from previous or current run
|
|
102
102
|
try
|
|
103
103
|
{
|
|
104
|
-
var panicLog = Path.Combine(
|
|
104
|
+
var panicLog = Path.Combine(RuntimeHost.LocalFolderPath, "nativescript-panic.log");
|
|
105
105
|
if (File.Exists(panicLog))
|
|
106
106
|
{
|
|
107
107
|
var content = File.ReadAllText(panicLog, Encoding.UTF8).Trim();
|
|
@@ -130,7 +130,7 @@ namespace __PROJECT_NAME__
|
|
|
130
130
|
|
|
131
131
|
public static string CrashLogPath()
|
|
132
132
|
{
|
|
133
|
-
try { return Path.Combine(
|
|
133
|
+
try { return Path.Combine(RuntimeHost.LocalFolderPath, "nativescript-crash.log"); }
|
|
134
134
|
catch { return null; }
|
|
135
135
|
}
|
|
136
136
|
|
|
@@ -272,7 +272,7 @@ namespace __PROJECT_NAME__
|
|
|
272
272
|
{
|
|
273
273
|
try
|
|
274
274
|
{
|
|
275
|
-
var logPath = Path.Combine(
|
|
275
|
+
var logPath = Path.Combine(RuntimeHost.LocalFolderPath, "nativescript-crash.log");
|
|
276
276
|
File.AppendAllText(logPath, content, Encoding.UTF8);
|
|
277
277
|
}
|
|
278
278
|
catch { }
|
|
@@ -32,6 +32,20 @@ namespace __PROJECT_NAME__
|
|
|
32
32
|
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_set_local_folder))]
|
|
33
33
|
private static extern void runtime_set_local_folder([MarshalAs(UnmanagedType.LPUTF8Str)] string localFolder);
|
|
34
34
|
|
|
35
|
+
// Escape hatch for apps packed with `nsbundle_pack --key-hex <hex>` (custom-key
|
|
36
|
+
// app.nsbundle containers). Must be called before runtime_init if used at all: apps
|
|
37
|
+
// packed with the default pepper (no --key-hex) never need to call this. Not wired to a
|
|
38
|
+
// default call site here; an app author supplies their own key material and calls this
|
|
39
|
+
// from Initialize() before runtime_init(...).
|
|
40
|
+
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_set_bundle_key))]
|
|
41
|
+
private static extern int runtime_set_bundle_key([MarshalAs(UnmanagedType.LPUTF8Str)] string keyHex);
|
|
42
|
+
|
|
43
|
+
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_read_protected_file))]
|
|
44
|
+
private static extern IntPtr runtime_read_protected_file([MarshalAs(UnmanagedType.LPUTF8Str)] string virtualPath);
|
|
45
|
+
|
|
46
|
+
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_free_protected_string))]
|
|
47
|
+
private static extern void runtime_free_protected_string(IntPtr ptr);
|
|
48
|
+
|
|
35
49
|
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_get_last_js_error))]
|
|
36
50
|
private static extern IntPtr runtime_get_last_js_error();
|
|
37
51
|
|
|
@@ -39,6 +53,7 @@ namespace __PROJECT_NAME__
|
|
|
39
53
|
private static extern void runtime_free_js_error(IntPtr ptr);
|
|
40
54
|
|
|
41
55
|
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_has_devtools))]
|
|
56
|
+
[return: MarshalAs(UnmanagedType.U1)]
|
|
42
57
|
private static extern bool runtime_has_devtools();
|
|
43
58
|
|
|
44
59
|
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_pump_timers))]
|
|
@@ -55,6 +70,18 @@ namespace __PROJECT_NAME__
|
|
|
55
70
|
}
|
|
56
71
|
|
|
57
72
|
#if DEBUG
|
|
73
|
+
// Engine runtimes (@nativescript/windows-<engine>) only: a debug host always allows
|
|
74
|
+
// dev-server modules (Vite HMR). The classic runtime derives this from its devtools build
|
|
75
|
+
// and doesn't export it.
|
|
76
|
+
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_set_debug_build))]
|
|
77
|
+
private static extern void runtime_set_debug_build(int debug);
|
|
78
|
+
|
|
79
|
+
private static void TrySetDebugBuild()
|
|
80
|
+
{
|
|
81
|
+
try { runtime_set_debug_build(1); }
|
|
82
|
+
catch (EntryPointNotFoundException) { }
|
|
83
|
+
}
|
|
84
|
+
|
|
58
85
|
[DllImport(NativeScriptLibrary, EntryPoint = nameof(ns_set_log_to_console))]
|
|
59
86
|
private static extern int ns_set_log_to_console(int enabled);
|
|
60
87
|
|
|
@@ -84,6 +111,21 @@ namespace __PROJECT_NAME__
|
|
|
84
111
|
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_free_string))]
|
|
85
112
|
private static extern void runtime_free_string(IntPtr ptr);
|
|
86
113
|
|
|
114
|
+
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_devtools_wait_for_debugger))]
|
|
115
|
+
[return: MarshalAs(UnmanagedType.U1)]
|
|
116
|
+
private static extern bool runtime_devtools_wait_for_debugger(long runtime, uint timeoutMs);
|
|
117
|
+
|
|
118
|
+
// iOS uses 41000 and Android 42000.
|
|
119
|
+
private const ushort DevtoolsPort = 43000;
|
|
120
|
+
private const uint DebuggerWaitTimeoutMs = 30000;
|
|
121
|
+
|
|
122
|
+
// LocalFolder sentinel files shared with the CLI's WindowsApplicationManager.
|
|
123
|
+
private const string InspectorMarker = "ns-inspector";
|
|
124
|
+
private const string DebugBreakMarker = "ns-debugbreak";
|
|
125
|
+
private const string DebuggerStartedMarker = "ns-debugger-started";
|
|
126
|
+
|
|
127
|
+
private bool _waitForDebugger;
|
|
128
|
+
|
|
87
129
|
public string DevtoolsFrontendUrl { get; private set; }
|
|
88
130
|
|
|
89
131
|
private bool _devtoolsAvailable;
|
|
@@ -104,7 +146,7 @@ namespace __PROJECT_NAME__
|
|
|
104
146
|
IntPtr urlPtr = IntPtr.Zero;
|
|
105
147
|
try
|
|
106
148
|
{
|
|
107
|
-
urlPtr = runtime_devtools_start(_runtime,
|
|
149
|
+
urlPtr = runtime_devtools_start(_runtime, DevtoolsPort);
|
|
108
150
|
if (urlPtr == IntPtr.Zero) return;
|
|
109
151
|
var wsUrl = Marshal.PtrToStringUTF8(urlPtr);
|
|
110
152
|
DevtoolsFrontendUrl = wsUrl != null
|
|
@@ -113,6 +155,8 @@ namespace __PROJECT_NAME__
|
|
|
113
155
|
if (DevtoolsFrontendUrl != null)
|
|
114
156
|
{
|
|
115
157
|
_devtoolsAvailable = true;
|
|
158
|
+
// The server may fall back to the next free port.
|
|
159
|
+
WriteMarker(DebuggerStartedMarker, new Uri(wsUrl).Port.ToString());
|
|
116
160
|
System.Diagnostics.Debug.WriteLine($"[NativeScript DevTools] {DevtoolsFrontendUrl}");
|
|
117
161
|
}
|
|
118
162
|
}
|
|
@@ -131,15 +175,41 @@ namespace __PROJECT_NAME__
|
|
|
131
175
|
private long _runtime;
|
|
132
176
|
private bool _initialized;
|
|
133
177
|
|
|
178
|
+
private static string _localFolderPath;
|
|
179
|
+
|
|
180
|
+
/// The app's local data folder: ApplicationData's LocalFolder for a packaged app, or
|
|
181
|
+
/// %LOCALAPPDATA%\<AssemblyName> for an unpackaged one (WindowsPackageType=None), which has
|
|
182
|
+
/// no package identity and therefore no ApplicationData.
|
|
183
|
+
internal static string LocalFolderPath
|
|
184
|
+
{
|
|
185
|
+
get
|
|
186
|
+
{
|
|
187
|
+
if (_localFolderPath != null) return _localFolderPath;
|
|
188
|
+
try
|
|
189
|
+
{
|
|
190
|
+
_localFolderPath = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
|
|
191
|
+
}
|
|
192
|
+
catch (InvalidOperationException)
|
|
193
|
+
{
|
|
194
|
+
var name = Assembly.GetEntryAssembly()?.GetName().Name ?? "NativeScriptApp";
|
|
195
|
+
_localFolderPath = Path.Combine(
|
|
196
|
+
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), name);
|
|
197
|
+
Directory.CreateDirectory(_localFolderPath);
|
|
198
|
+
}
|
|
199
|
+
return _localFolderPath;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
134
203
|
public void Initialize()
|
|
135
204
|
{
|
|
136
205
|
if (_initialized) return;
|
|
137
206
|
bool attached = false;
|
|
138
207
|
try { attached = AttachConsole(ATTACH_PARENT_PROCESS); } catch { }
|
|
139
208
|
runtime_install_ctrlc_handler(0);
|
|
140
|
-
runtime_set_local_folder(
|
|
209
|
+
runtime_set_local_folder(LocalFolderPath);
|
|
141
210
|
_runtime = runtime_init(AppContext.BaseDirectory);
|
|
142
211
|
#if DEBUG
|
|
212
|
+
TrySetDebugBuild();
|
|
143
213
|
var trySet = TrySetLogToConsole(true);
|
|
144
214
|
System.Diagnostics.Debug.WriteLine($"[NativeScript] TrySetLogToConsole returned={trySet}");
|
|
145
215
|
|
|
@@ -164,38 +234,85 @@ namespace __PROJECT_NAME__
|
|
|
164
234
|
}
|
|
165
235
|
}
|
|
166
236
|
catch { }
|
|
167
|
-
|
|
237
|
+
DeleteMarker(DebuggerStartedMarker);
|
|
238
|
+
var debugBreak = ConsumeMarker(DebugBreakMarker);
|
|
239
|
+
if (ConsumeMarker(InspectorMarker) || debugBreak)
|
|
240
|
+
{
|
|
168
241
|
StartDevtoolsSafely();
|
|
242
|
+
_waitForDebugger = debugBreak && _devtoolsAvailable;
|
|
243
|
+
}
|
|
169
244
|
#endif
|
|
170
245
|
_initialized = true;
|
|
171
246
|
}
|
|
172
247
|
|
|
173
248
|
#if DEBUG
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
private static bool ConsumeDebugBreakMarker()
|
|
249
|
+
private static string MarkerPath(string name) =>
|
|
250
|
+
Path.Combine(LocalFolderPath, name);
|
|
251
|
+
|
|
252
|
+
private static bool ConsumeMarker(string name)
|
|
179
253
|
{
|
|
180
254
|
try
|
|
181
255
|
{
|
|
182
|
-
var markerPath =
|
|
183
|
-
|
|
184
|
-
"ns-debugbreak");
|
|
185
|
-
if (!System.IO.File.Exists(markerPath))
|
|
256
|
+
var markerPath = MarkerPath(name);
|
|
257
|
+
if (!File.Exists(markerPath))
|
|
186
258
|
return false;
|
|
187
|
-
|
|
259
|
+
File.Delete(markerPath);
|
|
188
260
|
return true;
|
|
189
261
|
}
|
|
190
262
|
catch { return false; }
|
|
191
263
|
}
|
|
264
|
+
|
|
265
|
+
private static void WriteMarker(string name, string contents)
|
|
266
|
+
{
|
|
267
|
+
try { File.WriteAllText(MarkerPath(name), contents); }
|
|
268
|
+
catch (Exception ex)
|
|
269
|
+
{
|
|
270
|
+
System.Diagnostics.Debug.WriteLine($"[NativeScript DevTools] Could not write {name}: {ex.Message}");
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
private static void DeleteMarker(string name)
|
|
275
|
+
{
|
|
276
|
+
try { File.Delete(MarkerPath(name)); }
|
|
277
|
+
catch { }
|
|
278
|
+
}
|
|
192
279
|
#endif
|
|
193
280
|
|
|
281
|
+
/// Reads a file that may live inside a sealed app.nsbundle instead of on disk: tries the
|
|
282
|
+
/// protected-VFS native call first (cheap no-op when no bundle is loaded), falls back to
|
|
283
|
+
/// the real filesystem. `path` is whatever candidate the caller already built for
|
|
284
|
+
/// `File.Exists`/`File.ReadAllText`: the native side strips it down to the bundle's
|
|
285
|
+
/// virtual (app/App-relative) path itself, so no extra bookkeeping is needed here.
|
|
286
|
+
private static string TryReadVirtual(string path)
|
|
287
|
+
{
|
|
288
|
+
IntPtr ptr = IntPtr.Zero;
|
|
289
|
+
try
|
|
290
|
+
{
|
|
291
|
+
ptr = runtime_read_protected_file(path);
|
|
292
|
+
return ptr == IntPtr.Zero ? null : Marshal.PtrToStringUTF8(ptr);
|
|
293
|
+
}
|
|
294
|
+
catch { return null; }
|
|
295
|
+
finally { if (ptr != IntPtr.Zero) runtime_free_protected_string(ptr); }
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
private static bool VExists(string path) => TryReadVirtual(path) != null || File.Exists(path);
|
|
299
|
+
|
|
300
|
+
private static string VReadAllText(string path) => TryReadVirtual(path) ?? File.ReadAllText(path);
|
|
301
|
+
|
|
194
302
|
public void RunMainScript()
|
|
195
303
|
{
|
|
196
304
|
if (!_initialized)
|
|
197
305
|
throw new InvalidOperationException("Runtime must be initialized before running scripts.");
|
|
198
306
|
|
|
307
|
+
#if DEBUG
|
|
308
|
+
if (_waitForDebugger)
|
|
309
|
+
{
|
|
310
|
+
// --debug-brk: hold the first script until DevTools attaches.
|
|
311
|
+
_waitForDebugger = false;
|
|
312
|
+
if (!runtime_devtools_wait_for_debugger(_runtime, DebuggerWaitTimeoutMs))
|
|
313
|
+
System.Diagnostics.Debug.WriteLine("[NativeScript DevTools] No debugger attached, continuing.");
|
|
314
|
+
}
|
|
315
|
+
#endif
|
|
199
316
|
var entryPath = ResolveEntryScriptPath();
|
|
200
317
|
if (entryPath == null)
|
|
201
318
|
{
|
|
@@ -205,10 +322,14 @@ namespace __PROJECT_NAME__
|
|
|
205
322
|
|
|
206
323
|
var dir = Path.GetDirectoryName(Path.GetFullPath(entryPath));
|
|
207
324
|
var chunks = new List<string>();
|
|
208
|
-
|
|
325
|
+
// An ES-module entry (Vite's bundle.mjs) imports its own chunks; webpack's classic
|
|
326
|
+
// runtime.js/vendor.js prelude must not run in front of it (a stale pair can be left
|
|
327
|
+
// in app/ after switching bundlers).
|
|
328
|
+
var isModuleEntry = entryPath.EndsWith(".mjs", StringComparison.OrdinalIgnoreCase);
|
|
329
|
+
foreach (var chunkName in isModuleEntry ? Array.Empty<string>() : new[] { "runtime.js", "vendor.js" })
|
|
209
330
|
{
|
|
210
331
|
var chunkPath = Path.Combine(dir, chunkName);
|
|
211
|
-
if (
|
|
332
|
+
if (VExists(chunkPath) &&
|
|
212
333
|
!string.Equals(chunkPath, Path.GetFullPath(entryPath), StringComparison.OrdinalIgnoreCase))
|
|
213
334
|
{
|
|
214
335
|
chunks.Add(chunkPath);
|
|
@@ -218,10 +339,14 @@ namespace __PROJECT_NAME__
|
|
|
218
339
|
|
|
219
340
|
foreach (var scriptPath in chunks)
|
|
220
341
|
{
|
|
221
|
-
var script =
|
|
342
|
+
var script = VReadAllText(Path.GetFullPath(scriptPath));
|
|
222
343
|
try
|
|
223
344
|
{
|
|
224
|
-
|
|
345
|
+
// Modules resolve their imports (chunks, ~/ paths) relative to their own
|
|
346
|
+
// location, so they need the full path; classic scripts keep the short name
|
|
347
|
+
// their stack traces and code-cache keys have always used.
|
|
348
|
+
var name = isModuleEntry ? Path.GetFullPath(scriptPath) : Path.GetFileName(scriptPath);
|
|
349
|
+
runtime_runscript(_runtime, script, name);
|
|
225
350
|
}
|
|
226
351
|
catch (Exception ex)
|
|
227
352
|
{
|
|
@@ -260,7 +385,7 @@ namespace __PROJECT_NAME__
|
|
|
260
385
|
foreach (var dir in appDirCandidates)
|
|
261
386
|
{
|
|
262
387
|
var candidate = Path.Combine(dir, "package.json");
|
|
263
|
-
if (
|
|
388
|
+
if (VExists(candidate))
|
|
264
389
|
{
|
|
265
390
|
packageJsonPath = candidate;
|
|
266
391
|
resolvedBaseDir = dir;
|
|
@@ -269,7 +394,7 @@ namespace __PROJECT_NAME__
|
|
|
269
394
|
}
|
|
270
395
|
|
|
271
396
|
// Also accept package.json at the project root (parent of bin/).
|
|
272
|
-
if (packageJsonPath == null &&
|
|
397
|
+
if (packageJsonPath == null && VExists(Path.Combine(parentDir, "package.json")))
|
|
273
398
|
{
|
|
274
399
|
packageJsonPath = Path.Combine(parentDir, "package.json");
|
|
275
400
|
resolvedBaseDir = parentDir;
|
|
@@ -278,7 +403,7 @@ namespace __PROJECT_NAME__
|
|
|
278
403
|
string Fallback() =>
|
|
279
404
|
appDirCandidates
|
|
280
405
|
.SelectMany(d => new[] { Path.Combine(d, "bundle.js"), Path.Combine(d, "bundle.mjs") })
|
|
281
|
-
.FirstOrDefault(
|
|
406
|
+
.FirstOrDefault(VExists);
|
|
282
407
|
|
|
283
408
|
if (packageJsonPath == null)
|
|
284
409
|
return Fallback();
|
|
@@ -304,7 +429,7 @@ namespace __PROJECT_NAME__
|
|
|
304
429
|
|
|
305
430
|
private static RuntimePackageConfig ParsePackageConfig(string packageJsonPath)
|
|
306
431
|
{
|
|
307
|
-
using var doc = JsonDocument.Parse(
|
|
432
|
+
using var doc = JsonDocument.Parse(VReadAllText(packageJsonPath));
|
|
308
433
|
var config = new RuntimePackageConfig();
|
|
309
434
|
if (doc.RootElement.TryGetProperty("main", out var main) && main.ValueKind == JsonValueKind.String)
|
|
310
435
|
config.Main = main.GetString();
|
|
@@ -321,11 +446,11 @@ namespace __PROJECT_NAME__
|
|
|
321
446
|
foreach (var candidate in new[] { normalized, normalized + ".js", normalized + ".mjs" })
|
|
322
447
|
{
|
|
323
448
|
var direct = Path.IsPathRooted(candidate) ? candidate : Path.Combine(baseDir, candidate);
|
|
324
|
-
if (
|
|
449
|
+
if (VExists(direct)) return direct;
|
|
325
450
|
var appLower = Path.Combine(baseDir, "app", candidate);
|
|
326
|
-
if (
|
|
451
|
+
if (VExists(appLower)) return appLower;
|
|
327
452
|
var appUpper = Path.Combine(baseDir, "App", candidate);
|
|
328
|
-
if (
|
|
453
|
+
if (VExists(appUpper)) return appUpper;
|
|
329
454
|
}
|
|
330
455
|
return null;
|
|
331
456
|
}
|
|
@@ -25,19 +25,14 @@
|
|
|
25
25
|
<NSWindowsRoot>$(MSBuildProjectDirectory)\..</NSWindowsRoot>
|
|
26
26
|
</PropertyGroup>
|
|
27
27
|
|
|
28
|
-
<!-- Static Binding Generator (SBG) output folder and helper properties for integrating generated proxies. -->
|
|
29
28
|
<PropertyGroup>
|
|
30
|
-
<NSGenDir>$(BaseIntermediateOutputPath)_ns_\gen</NSGenDir>
|
|
31
|
-
<SBG_OUTPUT_DIR>$(MSBuildProjectDirectory)\$(NSGenDir)</SBG_OUTPUT_DIR>
|
|
32
29
|
<!-- Path to the windows-runtime repository root. Can be overridden by setting the environment
|
|
33
30
|
variable `NS_WINDOWS_RUNTIME_ROOT` (useful when building an app that lives outside the
|
|
34
31
|
runtime repo). If not set, fall back to the project parent directory (legacy behavior). -->
|
|
35
32
|
<WindowsRuntimeRepoRoot Condition="'$(WindowsRuntimeRepoRoot)'=='' and '$(NS_WINDOWS_RUNTIME_ROOT)' != ''">$(NS_WINDOWS_RUNTIME_ROOT)</WindowsRuntimeRepoRoot>
|
|
36
33
|
<WindowsRuntimeRepoRoot Condition="'$(WindowsRuntimeRepoRoot)'==''">$(MSBuildProjectDirectory)\..</WindowsRuntimeRepoRoot>
|
|
37
|
-
<SBGMetadataSource>$(SBG_OUTPUT_DIR)\sbg_metadata.json</SBGMetadataSource>
|
|
38
34
|
<!-- Resolve pre-built tool binaries shipped inside the npm package tools/ directory -->
|
|
39
35
|
<NSToolsDir>$(NSWindowsRoot)\tools</NSToolsDir>
|
|
40
|
-
<SbgExe Condition="Exists('$(NSToolsDir)\sbg.exe')">$(NSToolsDir)\sbg.exe</SbgExe>
|
|
41
36
|
<DotNetToolExe Condition="Exists('$(NSToolsDir)\dotnet-tool.exe')">$(NSToolsDir)\dotnet-tool.exe</DotNetToolExe>
|
|
42
37
|
</PropertyGroup>
|
|
43
38
|
|
|
@@ -87,12 +82,32 @@
|
|
|
87
82
|
<Content Include="Properties\Default.rd.xml" />
|
|
88
83
|
|
|
89
84
|
<!-- App JS/resource files — copied to the output directory on every build -->
|
|
90
|
-
|
|
85
|
+
<!-- Sealed source-protected bundle when present, takes
|
|
86
|
+
priority over the plaintext app\ tree; produced by the nsbundle_pack packer tool. -->
|
|
87
|
+
<Content Include="app.nsbundle" Condition="Exists('app.nsbundle')">
|
|
88
|
+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
89
|
+
</Content>
|
|
90
|
+
<Content Include="app\**\*" Condition="!Exists('app.nsbundle')">
|
|
91
|
+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
92
|
+
</Content>
|
|
93
|
+
|
|
94
|
+
<!-- App_Resources: platform-specific assets (images, fonts, etc.). C# sources anywhere under
|
|
95
|
+
App_Resources\Windows (e.g. App_Resources\Windows\src\*.cs) and in plugins\<plugin>\ are
|
|
96
|
+
compiled into the app by the SDK's default Compile glob — the counterpart of Java/Kotlin in
|
|
97
|
+
App_Resources/Android/src and Objective-C/Swift in App_Resources/iOS/src — and JavaScript
|
|
98
|
+
reaches their types by namespace. Sources and MSBuild files aren't copied to the output. -->
|
|
99
|
+
<Content Include="App_Resources\**\*" Exclude="App_Resources\**\*.cs;App_Resources\**\*.csproj;App_Resources\**\*.props;App_Resources\**\*.targets" Condition="Exists('App_Resources')">
|
|
91
100
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
92
101
|
</Content>
|
|
93
102
|
|
|
94
|
-
<!--
|
|
95
|
-
|
|
103
|
+
<!-- The app's metadata filter (App_Resources/Windows/native-api-usage.json, which the CLI writes
|
|
104
|
+
out next to this project): the runtime reads it next to the exe. -->
|
|
105
|
+
<Content Include="$(NSWindowsRoot)\whitelist.mdg" Condition="Exists('$(NSWindowsRoot)\whitelist.mdg')">
|
|
106
|
+
<Link>whitelist.mdg</Link>
|
|
107
|
+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
108
|
+
</Content>
|
|
109
|
+
<Content Include="$(NSWindowsRoot)\blacklist.mdg" Condition="Exists('$(NSWindowsRoot)\blacklist.mdg')">
|
|
110
|
+
<Link>blacklist.mdg</Link>
|
|
96
111
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
97
112
|
</Content>
|
|
98
113
|
|
|
@@ -170,44 +185,23 @@
|
|
|
170
185
|
SkipUnchangedFiles="true" />
|
|
171
186
|
</Target>
|
|
172
187
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
<
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
188
|
+
<!-- A filter the app dropped must not stay in force from an earlier build's copy. -->
|
|
189
|
+
<Target Name="RemoveStaleMetadataFilter" BeforeTargets="CopyFilesToOutputDirectory">
|
|
190
|
+
<Delete Files="$(OutDir)whitelist.mdg" Condition="!Exists('$(NSWindowsRoot)\whitelist.mdg')" />
|
|
191
|
+
<Delete Files="$(OutDir)blacklist.mdg" Condition="!Exists('$(NSWindowsRoot)\blacklist.mdg')" />
|
|
192
|
+
</Target>
|
|
193
|
+
|
|
194
|
+
<!-- Run dotnet-tool to auto-detect .NET usage and publish/copy DotNetBridge. Prefer the pre-built
|
|
195
|
+
binary shipped in the npm package; fall back to cargo run for dev. JS subclasses of .NET and
|
|
196
|
+
WinRT classes need no generated code: the bridge creates their managed types at runtime. -->
|
|
197
|
+
<Target Name="RunDotNetTool" BeforeTargets="CoreCompile">
|
|
198
|
+
<Exec Command=""$(DotNetToolExe)" --app-root "$(MSBuildProjectDirectory)" --dir App"
|
|
181
199
|
Condition="'$(DotNetToolExe)' != ''" />
|
|
182
200
|
<Exec WorkingDirectory="$(WindowsRuntimeRepoRoot)"
|
|
183
|
-
Command="cargo run --quiet --manifest-path "$(WindowsRuntimeRepoRoot)\Cargo.toml" -p dotnet-tool -- --app-root "$(MSBuildProjectDirectory)" --dir App
|
|
201
|
+
Command="cargo run --quiet --manifest-path "$(WindowsRuntimeRepoRoot)\Cargo.toml" -p dotnet-tool -- --app-root "$(MSBuildProjectDirectory)" --dir App"
|
|
184
202
|
Condition="'$(DotNetToolExe)' == '' and Exists('$(WindowsRuntimeRepoRoot)\Cargo.toml')" />
|
|
185
|
-
<!-- Run SBG to generate C# proxies from captured metadata.
|
|
186
|
-
sbg_metadata.json is written by __nsProxyAutoCapture when the app runs
|
|
187
|
-
with extensions that use .extend() / @Interfaces / @CSharpProxy.
|
|
188
|
-
Search order: pre-built tools/ binary, then cargo run for dev. -->
|
|
189
|
-
<Exec
|
|
190
|
-
Command=""$(SbgExe)""
|
|
191
|
-
EnvironmentVariables="NSWINRT_AUTO_METADATA_PATH=$(SBGMetadataSource);SBG_OUTPUT_DIR=$(SBG_OUTPUT_DIR);SBG_METADATA_SOURCE=$(SBGMetadataSource);SBG_TARGET_FRAMEWORK=$(TargetFramework);SBG_TARGET_PLATFORM_MIN_VERSION=$(TargetPlatformMinVersion);SBG_USE_UWP=false;SBG_APP_CS_SOURCES_DIR=$(MSBuildProjectDirectory)"
|
|
192
|
-
Condition="'$(SbgExe)' != '' and Exists('$(SBGMetadataSource)')" />
|
|
193
|
-
<Exec WorkingDirectory="$(WindowsRuntimeRepoRoot)"
|
|
194
|
-
Command="cargo run --quiet --manifest-path "$(WindowsRuntimeRepoRoot)\Cargo.toml" -p sbg"
|
|
195
|
-
EnvironmentVariables="NSWINRT_AUTO_METADATA_PATH=$(SBGMetadataSource);SBG_OUTPUT_DIR=$(SBG_OUTPUT_DIR);SBG_METADATA_SOURCE=$(SBGMetadataSource);SBG_TARGET_FRAMEWORK=$(TargetFramework);SBG_TARGET_PLATFORM_MIN_VERSION=$(TargetPlatformMinVersion);SBG_USE_UWP=false;SBG_APP_CS_SOURCES_DIR=$(MSBuildProjectDirectory)"
|
|
196
|
-
Condition="'$(SbgExe)' == '' and Exists('$(SBGMetadataSource)') and Exists('$(WindowsRuntimeRepoRoot)\Cargo.toml')" />
|
|
197
203
|
</Target>
|
|
198
204
|
|
|
199
|
-
<Target Name="CleanStaticBindingGeneratorOutput" AfterTargets="CoreClean">
|
|
200
|
-
<RemoveDir Directories="$(NSGenDir)" Condition="Exists('$(NSGenDir)')" />
|
|
201
|
-
</Target>
|
|
202
|
-
|
|
203
|
-
<ItemGroup>
|
|
204
|
-
<Compile Include="$(NSGenDir)\NSWinRTProxies\**\*.cs" Visible="false" Condition="Exists('$(NSGenDir)\NSWinRTProxies')" />
|
|
205
|
-
<Compile Remove="$(NSGenDir)\NSWinRTProxies\obj\**\*.cs" Condition="Exists('$(NSGenDir)\NSWinRTProxies\obj')" />
|
|
206
|
-
<Content Include="$(NSGenDir)\sbg-manifest.json" Link="sbg-manifest.json" CopyToOutputDirectory="PreserveNewest" Condition="Exists('$(NSGenDir)\sbg-manifest.json')" />
|
|
207
|
-
<Content Include="$(NSGenDir)\NSWinRTProxies\bin\Release\**\NSWinRTProxies.dll" Link="NSWinRTProxies.dll" CopyToOutputDirectory="PreserveNewest" Condition="Exists('$(NSGenDir)\NSWinRTProxies\bin\Release')" />
|
|
208
|
-
</ItemGroup>
|
|
209
|
-
|
|
210
|
-
|
|
211
205
|
<!-- Ensure bridge files are included in the final `dotnet publish` output. -->
|
|
212
206
|
<Target Name="CopyDotNetBridgeToPublishDir"
|
|
213
207
|
AfterTargets="Publish"
|
|
@@ -17,6 +17,20 @@ internal readonly struct WinRtRef(long ptr)
|
|
|
17
17
|
public readonly long Ptr = ptr;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
// A JS function passed where a delegate is expected (tag 0x0C): the runtime's callback id, wrapped
|
|
21
|
+
// in a delegate of the parameter's type when the call's arguments are coerced.
|
|
22
|
+
internal readonly struct JsFunctionRef(int id)
|
|
23
|
+
{
|
|
24
|
+
public readonly int Id = id;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// A plain JS object (tag 0x0D) as JSON, deserialized into the struct/record/class the parameter or
|
|
28
|
+
// return type expects (e.g. `{ Width: 120, Height: 40 }` for Windows.Foundation.Size).
|
|
29
|
+
internal sealed class JsJsonValue(string json)
|
|
30
|
+
{
|
|
31
|
+
public readonly string Json = json;
|
|
32
|
+
}
|
|
33
|
+
|
|
20
34
|
internal ref struct BinReader(ReadOnlySpan<byte> buf)
|
|
21
35
|
{
|
|
22
36
|
private readonly ReadOnlySpan<byte> _buf = buf;
|
|
@@ -24,6 +38,8 @@ internal ref struct BinReader(ReadOnlySpan<byte> buf)
|
|
|
24
38
|
|
|
25
39
|
public byte ReadByte() => _buf[_pos++];
|
|
26
40
|
|
|
41
|
+
public bool HasMore => _pos < _buf.Length;
|
|
42
|
+
|
|
27
43
|
public int ReadI32()
|
|
28
44
|
{
|
|
29
45
|
var v = BinaryPrimitives.ReadInt32LittleEndian(_buf[_pos..]);
|
|
@@ -96,6 +112,8 @@ internal ref struct BinReader(ReadOnlySpan<byte> buf)
|
|
|
96
112
|
0x05 => (object)ReadString16(),
|
|
97
113
|
0x06 => (object)new HandleRef(ReadI32()),
|
|
98
114
|
0x0A => (object)new WinRtRef(ReadI64()),
|
|
115
|
+
0x0C => (object)new JsFunctionRef(ReadI32()),
|
|
116
|
+
0x0D => (object)new JsJsonValue(ReadString32()),
|
|
99
117
|
_ => null,
|
|
100
118
|
};
|
|
101
119
|
}
|