@nativescript/windows-quickjs 0.1.0-alpha.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 (48) hide show
  1. package/README.md +27 -0
  2. package/framework/__PROJECT_NAME__/App.xaml +13 -0
  3. package/framework/__PROJECT_NAME__/App.xaml.cs +240 -0
  4. package/framework/__PROJECT_NAME__/Assets/SplashScreen.png +0 -0
  5. package/framework/__PROJECT_NAME__/Assets/Square150x150Logo.png +0 -0
  6. package/framework/__PROJECT_NAME__/Assets/Square44x44Logo.png +0 -0
  7. package/framework/__PROJECT_NAME__/Assets/StoreLogo.png +0 -0
  8. package/framework/__PROJECT_NAME__/Assets/Wide310x150Logo.png +0 -0
  9. package/framework/__PROJECT_NAME__/CrashDiagnostics.cs +281 -0
  10. package/framework/__PROJECT_NAME__/Directory.Build.props +15 -0
  11. package/framework/__PROJECT_NAME__/Directory.Build.targets +106 -0
  12. package/framework/__PROJECT_NAME__/Package.appxmanifest +35 -0
  13. package/framework/__PROJECT_NAME__/Program.cs +34 -0
  14. package/framework/__PROJECT_NAME__/Properties/Default.rd.xml +9 -0
  15. package/framework/__PROJECT_NAME__/RuntimeHost.cs +359 -0
  16. package/framework/__PROJECT_NAME__/__PROJECT_NAME__.csproj +263 -0
  17. package/framework/dotnet-bridge/BinaryProtocol.cs +161 -0
  18. package/framework/dotnet-bridge/Bridge.BinaryDispatch.cs +373 -0
  19. package/framework/dotnet-bridge/Bridge.Dispatch.cs +597 -0
  20. package/framework/dotnet-bridge/Bridge.JsDelegate.cs +244 -0
  21. package/framework/dotnet-bridge/Bridge.Proxy.cs +573 -0
  22. package/framework/dotnet-bridge/Bridge.TaskHelper.cs +207 -0
  23. package/framework/dotnet-bridge/Bridge.cs +724 -0
  24. package/framework/dotnet-bridge/DispatchTypes.cs +333 -0
  25. package/framework/dotnet-bridge/DotNetBridge.csproj +30 -0
  26. package/framework/dotnet-bridge/publish_build/DotNetBridge.deps.json +23 -0
  27. package/framework/dotnet-bridge/publish_build/DotNetBridge.dll +0 -0
  28. package/framework/dotnet-bridge/publish_build/DotNetBridge.pdb +0 -0
  29. package/framework/dotnet-bridge/publish_build/DotNetBridge.runtimeconfig.json +14 -0
  30. package/framework/libs/x64/nativescript.dll +0 -0
  31. package/framework/tools/ManifestMerger/ManifestMerger.deps.json +24 -0
  32. package/framework/tools/ManifestMerger/ManifestMerger.dll +0 -0
  33. package/framework/tools/ManifestMerger/ManifestMerger.pdb +0 -0
  34. package/framework/tools/dotnet-tool-arm64.exe +0 -0
  35. package/framework/tools/dotnet-tool-x64.exe +0 -0
  36. package/framework/tools/dotnet-tool.exe +0 -0
  37. package/framework/tools/dotnet-typings-gen/dotnet-typings-gen.deps.json +23 -0
  38. package/framework/tools/dotnet-typings-gen/dotnet-typings-gen.dll +0 -0
  39. package/framework/tools/dotnet-typings-gen/dotnet-typings-gen.exe +0 -0
  40. package/framework/tools/dotnet-typings-gen/dotnet-typings-gen.pdb +0 -0
  41. package/framework/tools/dotnet-typings-gen/dotnet-typings-gen.runtimeconfig.json +13 -0
  42. package/framework/tools/sbg-arm64.exe +0 -0
  43. package/framework/tools/sbg-x64.exe +0 -0
  44. package/framework/tools/sbg.exe +0 -0
  45. package/framework/tools/typings-generator-arm64.exe +0 -0
  46. package/framework/tools/typings-generator-x64.exe +0 -0
  47. package/framework/tools/typings-generator.exe +0 -0
  48. package/package.json +43 -0
@@ -0,0 +1,106 @@
1
+ <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2
+ <!-- Directory.Build.targets for the Windows project template.
3
+ This file applies manifest overrides at build time using XmlPoke.
4
+ Place in the template root so generated projects inherit it. -->
5
+ <!-- Default properties are provided in Directory.Build.props so they can be
6
+ easily overridden per-app or via MSBuild /p: properties. -->
7
+
8
+ <PropertyGroup>
9
+ <ManifestMergerAssembly Condition="'$(ManifestMergerAssembly)' == ''">$(MSBuildThisFileDirectory)..\tools\ManifestMerger\ManifestMerger.dll</ManifestMergerAssembly>
10
+ <ValidateMergedManifest Condition="'$(ValidateMergedManifest)' == ''">false</ValidateMergedManifest>
11
+ <TreatManifestValidationErrorsAsWarnings Condition="'$(TreatManifestValidationErrorsAsWarnings)' == ''">false</TreatManifestValidationErrorsAsWarnings>
12
+ <LogManifestMergeDiagnosticsAsWarnings Condition="'$(LogManifestMergeDiagnosticsAsWarnings)' == ''">false</LogManifestMergeDiagnosticsAsWarnings>
13
+ </PropertyGroup>
14
+
15
+ <UsingTask TaskName="MergeAppxManifest" AssemblyFile="$(ManifestMergerAssembly)" Condition="Exists('$(ManifestMergerAssembly)')" />
16
+
17
+ <Target Name="MergeAppResourcesManifest" AfterTargets="ApplyManifestOverrides" Condition="Exists('$(MSBuildProjectDirectory)\Package.appxmanifest')">
18
+ <PropertyGroup>
19
+ <_AppResourcesManifest>$(MSBuildProjectDirectory)\App_Resources\Windows\Package.appxmanifest</_AppResourcesManifest>
20
+ <!-- Allow CLI or callers to override the source manifest via MSBuild property 'AppResourcesManifestPath' -->
21
+ <_AppResourcesManifest Condition="'$(AppResourcesManifestPath)' != ''">$(AppResourcesManifestPath)</_AppResourcesManifest>
22
+ <!-- Fallback template manifest name (no '.partial' suffix) -->
23
+ <_PartialManifest>$(MSBuildProjectDirectory)\Package.appxmanifest</_PartialManifest>
24
+ <_ManifestToMerge>$(_PartialManifest)</_ManifestToMerge>
25
+ <_ManifestToMerge Condition="Exists('$(_AppResourcesManifest)')">$(_AppResourcesManifest)</_ManifestToMerge>
26
+ </PropertyGroup>
27
+ <ItemGroup>
28
+ <_ManifestMergerSchemaFiles Include="$(ManifestMergerSchemaFiles)" Condition="'$(ManifestMergerSchemaFiles)' != ''" />
29
+ </ItemGroup>
30
+ <Message Text="Merging app manifest (if present) into generated Package.appxmanifest (app wins)" Importance="Low" />
31
+ <MergeAppxManifest SourceManifest="$(_ManifestToMerge)"
32
+ TargetManifest="$(MSBuildProjectDirectory)\Package.appxmanifest"
33
+ ValidateMergedManifest="$(ValidateMergedManifest)"
34
+ TreatValidationErrorsAsWarnings="$(TreatManifestValidationErrorsAsWarnings)"
35
+ LogMergeDiagnosticsAsWarnings="$(LogManifestMergeDiagnosticsAsWarnings)"
36
+ SchemaFiles="@(_ManifestMergerSchemaFiles)"
37
+ Condition="Exists('$(ManifestMergerAssembly)') and Exists('$(_ManifestToMerge)')" />
38
+ </Target>
39
+
40
+ <Target Name="WarnMissingManifestMerger"
41
+ BeforeTargets="MergeAppResourcesManifest"
42
+ Condition="Exists('$(MSBuildProjectDirectory)\Package.appxmanifest') and !Exists('$(ManifestMergerAssembly)')">
43
+ <Warning Text="ManifestMerger task assembly was not found at '$(ManifestMergerAssembly)'; app manifest resources will not be merged." />
44
+ </Target>
45
+
46
+ <Target Name="ApplyManifestOverrides" BeforeTargets="BeforeBuild" Condition="Exists('$(MSBuildProjectDirectory)\Package.appxmanifest')">
47
+ <Message Text="Applying manifest overrides (VisualElements, logos, splash) via XmlPoke..." Importance="High" />
48
+
49
+ <!-- DisplayName (app tile / taskbar / Start / alt-tab) -->
50
+ <XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
51
+ Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@DisplayName"
52
+ Value="$(AppDisplayName)"
53
+ Condition="'$(AppDisplayName)' != ''" />
54
+
55
+ <!-- Package DisplayName (Properties) — keep it in sync with the app name instead of leaving the
56
+ raw project name. The XmlPoke above only touches the per-app VisualElements name. -->
57
+ <XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
58
+ Query="/*[local-name()='Package']/*[local-name()='Properties']/*[local-name()='DisplayName']"
59
+ Value="$(AppDisplayName)"
60
+ Condition="'$(AppDisplayName)' != ''" />
61
+
62
+ <!-- Description -->
63
+ <XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
64
+ Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@Description"
65
+ Value="$(AppDescription)"
66
+ Condition="'$(AppDescription)' != ''" />
67
+
68
+ <!-- Logos -->
69
+ <XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
70
+ Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@Square150x150Logo"
71
+ Value="$(Square150x150Logo)"
72
+ Condition="'$(Square150x150Logo)' != ''" />
73
+
74
+ <XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
75
+ Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@Square44x44Logo"
76
+ Value="$(Square44x44Logo)"
77
+ Condition="'$(Square44x44Logo)' != ''" />
78
+
79
+ <XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
80
+ Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/*[local-name()='DefaultTile']/@Wide310x150Logo"
81
+ Value="$(Wide310x150Logo)"
82
+ Condition="'$(Wide310x150Logo)' != ''" />
83
+
84
+ <XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
85
+ Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@StoreLogo"
86
+ Value="$(StoreLogo)"
87
+ Condition="'$(StoreLogo)' != ''" />
88
+
89
+ <XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
90
+ Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@LockScreenLogo"
91
+ Value="$(LockScreenLogo)"
92
+ Condition="'$(LockScreenLogo)' != ''" />
93
+
94
+ <!-- BackgroundColor and SplashScreen image -->
95
+ <XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
96
+ Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@BackgroundColor"
97
+ Value="$(SplashBackgroundColor)"
98
+ Condition="'$(SplashBackgroundColor)' != ''" />
99
+
100
+ <XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
101
+ Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/*[local-name()='SplashScreen']/@Image"
102
+ Value="$(SplashImage)"
103
+ Condition="'$(SplashImage)' != ''" />
104
+
105
+ </Target>
106
+ </Project>
@@ -0,0 +1,35 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <Package
3
+ xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
4
+ xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
5
+ xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
6
+ IgnorableNamespaces="uap rescap">
7
+ <Identity Name="__APP_IDENTIFIER__" Publisher="CN=__PROJECT_NAME__" Version="1.0.0.0" />
8
+ <Properties>
9
+ <DisplayName>__PROJECT_NAME__</DisplayName>
10
+ <PublisherDisplayName>__PROJECT_NAME__</PublisherDisplayName>
11
+ <Logo>Assets\StoreLogo.png</Logo>
12
+ </Properties>
13
+ <Dependencies>
14
+ <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.26100.0" />
15
+ <!-- WinUI3 / Windows App SDK 1.6 framework package (framework-dependent). Required so the
16
+ registered app can activate Microsoft.UI.Xaml.* (else REGDB_E_CLASSNOTREG at startup). -->
17
+ <PackageDependency Name="Microsoft.WindowsAppRuntime.1.6" MinVersion="6000.0.0.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
18
+ </Dependencies>
19
+ <Resources>
20
+ <Resource Language="en-US" />
21
+ </Resources>
22
+ <Applications>
23
+ <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="Windows.FullTrustApplication">
24
+ <uap:VisualElements DisplayName="__PROJECT_NAME__" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="A NativeScript Windows application" BackgroundColor="#65ADF1">
25
+ <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" />
26
+ <uap:SplashScreen Image="Assets\SplashScreen.png" />
27
+ </uap:VisualElements>
28
+ </Application>
29
+ </Applications>
30
+ <Capabilities>
31
+ <rescap:Capability Name="runFullTrust" />
32
+ <Capability Name="internetClient" />
33
+ <Capability Name="privateNetworkClientServer" />
34
+ </Capabilities>
35
+ </Package>
@@ -0,0 +1,34 @@
1
+ using System;
2
+ using System.Threading;
3
+ using Microsoft.UI.Dispatching;
4
+ using Microsoft.UI.Xaml;
5
+ using WinRT;
6
+
7
+ // Windows-only WinUI desktop app. The custom entry point (DISABLE_XAML_GENERATED_MAIN)
8
+ // has no platform attribute, so CA1416 treats every Windows API call site as "reachable
9
+ // on all platforms." Declaring the assembly's supported platform once tells the analyzer
10
+ // the whole assembly only runs on Windows >= 17763, silencing those false positives.
11
+ [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.17763.0")]
12
+
13
+ namespace __PROJECT_NAME__
14
+ {
15
+ public static class Program
16
+ {
17
+ [System.STAThread]
18
+ public static void Main(string[] args)
19
+ {
20
+ ComWrappersSupport.InitializeComWrappers();
21
+
22
+ Application.Start((_callbackParams) =>
23
+ {
24
+ var dispatcherQueue = DispatcherQueue.GetForCurrentThread();
25
+ if (dispatcherQueue != null)
26
+ {
27
+ SynchronizationContext.SetSynchronizationContext(new DispatcherQueueSynchronizationContext(dispatcherQueue));
28
+ }
29
+
30
+ new App();
31
+ });
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,9 @@
1
+ <!--
2
+ Runtime Directives for .NET Native.
3
+ See https://go.microsoft.com/fwlink/?LinkID=391919
4
+ -->
5
+ <Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
6
+ <Application>
7
+ <Assembly Name="*Application*" Dynamic="Required All" />
8
+ </Application>
9
+ </Directives>
@@ -0,0 +1,359 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.IO;
4
+ using System.Linq;
5
+ using System.Reflection;
6
+ using System.Runtime.InteropServices;
7
+ using System.Text.Json;
8
+
9
+ namespace __PROJECT_NAME__
10
+ {
11
+ internal sealed class RuntimeHost : IDisposable
12
+ {
13
+ private const string NativeScriptLibrary = "nativescript";
14
+
15
+ [DllImport("kernel32.dll")]
16
+ private static extern bool AttachConsole(int dwProcessId);
17
+
18
+ private const int ATTACH_PARENT_PROCESS = -1;
19
+
20
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_init))]
21
+ private static extern long runtime_init([MarshalAs(UnmanagedType.LPUTF8Str)] string appRoot);
22
+
23
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_deinit))]
24
+ private static extern void runtime_deinit(long runtime);
25
+
26
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_runscript))]
27
+ private static extern void runtime_runscript(long runtime, [MarshalAs(UnmanagedType.LPUTF8Str)] string script, [MarshalAs(UnmanagedType.LPUTF8Str)] string filename);
28
+
29
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_install_ctrlc_handler))]
30
+ private static extern void runtime_install_ctrlc_handler(int exitCode);
31
+
32
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_set_local_folder))]
33
+ private static extern void runtime_set_local_folder([MarshalAs(UnmanagedType.LPUTF8Str)] string localFolder);
34
+
35
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_get_last_js_error))]
36
+ private static extern IntPtr runtime_get_last_js_error();
37
+
38
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_free_js_error))]
39
+ private static extern void runtime_free_js_error(IntPtr ptr);
40
+
41
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_has_devtools))]
42
+ private static extern bool runtime_has_devtools();
43
+
44
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_pump_timers))]
45
+ private static extern void runtime_pump_timers();
46
+
47
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_notify_app_event))]
48
+ private static extern void runtime_notify_app_event(long runtime, int kind, [MarshalAs(UnmanagedType.LPUTF8Str)] string message);
49
+
50
+ public void NotifyAppEvent(int kind, string message = null)
51
+ {
52
+ if (!_initialized) return;
53
+ try { runtime_notify_app_event(_runtime, kind, message); }
54
+ catch { }
55
+ }
56
+
57
+ #if DEBUG
58
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(ns_set_log_to_console))]
59
+ private static extern int ns_set_log_to_console(int enabled);
60
+
61
+ public static bool TrySetLogToConsole(bool enabled)
62
+ {
63
+ try { return ns_set_log_to_console(enabled ? 1 : 0) == 1; }
64
+ catch { return false; }
65
+ }
66
+ #else
67
+ public static bool TrySetLogToConsole(bool enabled) => false;
68
+ #endif
69
+
70
+ public void PumpTimers()
71
+ {
72
+ if (!_initialized) return;
73
+ try { runtime_pump_timers(); }
74
+ catch { }
75
+ }
76
+
77
+ #if DEBUG
78
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_devtools_start))]
79
+ private static extern IntPtr runtime_devtools_start(long runtime, ushort port);
80
+
81
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_devtools_pump))]
82
+ private static extern void runtime_devtools_pump(long runtime);
83
+
84
+ [DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_free_string))]
85
+ private static extern void runtime_free_string(IntPtr ptr);
86
+
87
+ public string DevtoolsFrontendUrl { get; private set; }
88
+
89
+ private bool _devtoolsAvailable;
90
+
91
+ public void PumpDevtools()
92
+ {
93
+ if (!_initialized || !_devtoolsAvailable) return;
94
+ try { runtime_devtools_pump(_runtime); }
95
+ catch (Exception ex)
96
+ {
97
+ System.Diagnostics.Debug.WriteLine($"[NativeScript DevTools] Pump failed: {ex.Message}");
98
+ }
99
+ }
100
+
101
+ private void StartDevtoolsSafely()
102
+ {
103
+ if (!runtime_has_devtools()) return;
104
+ IntPtr urlPtr = IntPtr.Zero;
105
+ try
106
+ {
107
+ urlPtr = runtime_devtools_start(_runtime, 42000);
108
+ if (urlPtr == IntPtr.Zero) return;
109
+ var wsUrl = Marshal.PtrToStringUTF8(urlPtr);
110
+ DevtoolsFrontendUrl = wsUrl != null
111
+ ? $"devtools://devtools/bundled/inspector.html?ws={wsUrl.Replace("ws://", "")}"
112
+ : null;
113
+ if (DevtoolsFrontendUrl != null)
114
+ {
115
+ _devtoolsAvailable = true;
116
+ System.Diagnostics.Debug.WriteLine($"[NativeScript DevTools] {DevtoolsFrontendUrl}");
117
+ }
118
+ }
119
+ catch (Exception ex)
120
+ {
121
+ DevtoolsFrontendUrl = null;
122
+ System.Diagnostics.Debug.WriteLine($"[NativeScript DevTools] Start failed: {ex.Message}");
123
+ }
124
+ finally
125
+ {
126
+ if (urlPtr != IntPtr.Zero) runtime_free_string(urlPtr);
127
+ }
128
+ }
129
+ #endif
130
+
131
+ private long _runtime;
132
+ private bool _initialized;
133
+
134
+ public void Initialize()
135
+ {
136
+ if (_initialized) return;
137
+ bool attached = false;
138
+ try { attached = AttachConsole(ATTACH_PARENT_PROCESS); } catch { }
139
+ runtime_install_ctrlc_handler(0);
140
+ runtime_set_local_folder(Windows.Storage.ApplicationData.Current.LocalFolder.Path);
141
+ _runtime = runtime_init(AppContext.BaseDirectory);
142
+ #if DEBUG
143
+ var trySet = TrySetLogToConsole(true);
144
+ System.Diagnostics.Debug.WriteLine($"[NativeScript] TrySetLogToConsole returned={trySet}");
145
+
146
+ // Also notify the managed bridge (if present) so managed-side
147
+ // diagnostics follow the runtime toggle. Use reflection to avoid a
148
+ // hard compile-time dependency on the bridge assembly.
149
+ try
150
+ {
151
+ foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
152
+ {
153
+ try
154
+ {
155
+ var t = asm.GetType("NativeScriptBridge.Bridge");
156
+ if (t is null) continue;
157
+ var m = t.GetMethod("SetLogToConsole", BindingFlags.Public | BindingFlags.Static);
158
+ if (m is null) continue;
159
+ m.Invoke(null, new object[] { true });
160
+ System.Diagnostics.Debug.WriteLine($"[NativeScript] Invoked Bridge.SetLogToConsole on {asm.GetName().Name}");
161
+ break;
162
+ }
163
+ catch { }
164
+ }
165
+ }
166
+ catch { }
167
+ if (ConsumeDebugBreakMarker())
168
+ StartDevtoolsSafely();
169
+ #endif
170
+ _initialized = true;
171
+ }
172
+
173
+ #if DEBUG
174
+ /// <summary>
175
+ /// Returns true and deletes the marker if the CLI wrote ns-debugbreak to LocalFolder,
176
+ /// matching the Android sentinel-file pattern used by the NativeScript CLI.
177
+ /// </summary>
178
+ private static bool ConsumeDebugBreakMarker()
179
+ {
180
+ try
181
+ {
182
+ var markerPath = System.IO.Path.Combine(
183
+ Windows.Storage.ApplicationData.Current.LocalFolder.Path,
184
+ "ns-debugbreak");
185
+ if (!System.IO.File.Exists(markerPath))
186
+ return false;
187
+ System.IO.File.Delete(markerPath);
188
+ return true;
189
+ }
190
+ catch { return false; }
191
+ }
192
+ #endif
193
+
194
+ public void RunMainScript()
195
+ {
196
+ if (!_initialized)
197
+ throw new InvalidOperationException("Runtime must be initialized before running scripts.");
198
+
199
+ var entryPath = ResolveEntryScriptPath();
200
+ if (entryPath == null)
201
+ {
202
+ System.Diagnostics.Debug.WriteLine("[NativeScript Runtime] No entry script found — bundle missing from app directory.");
203
+ return;
204
+ }
205
+
206
+ var dir = Path.GetDirectoryName(Path.GetFullPath(entryPath));
207
+ var chunks = new List<string>();
208
+ foreach (var chunkName in new[] { "runtime.js", "vendor.js" })
209
+ {
210
+ var chunkPath = Path.Combine(dir, chunkName);
211
+ if (File.Exists(chunkPath) &&
212
+ !string.Equals(chunkPath, Path.GetFullPath(entryPath), StringComparison.OrdinalIgnoreCase))
213
+ {
214
+ chunks.Add(chunkPath);
215
+ }
216
+ }
217
+ chunks.Add(entryPath);
218
+
219
+ foreach (var scriptPath in chunks)
220
+ {
221
+ var script = File.ReadAllText(Path.GetFullPath(scriptPath));
222
+ try
223
+ {
224
+ runtime_runscript(_runtime, script, Path.GetFileName(scriptPath));
225
+ }
226
+ catch (Exception ex)
227
+ {
228
+ CrashDiagnostics.WriteExceptionReport("RuntimeHost.RunMainScript", ex, "Script=" + scriptPath);
229
+ System.Diagnostics.Debug.WriteLine($"[NativeScript Runtime] Script execution failed ({scriptPath}): {ex}");
230
+ throw;
231
+ }
232
+ }
233
+ }
234
+
235
+ private sealed class RuntimePackageConfig
236
+ {
237
+ public string Main { get; set; } = string.Empty;
238
+ public string WindowsMain { get; set; } = string.Empty;
239
+ }
240
+
241
+ private static string ResolveEntryScriptPath()
242
+ {
243
+ var baseDir = AppContext.BaseDirectory;
244
+ // EXE lives in <project>/bin/; webpack bundle lives in <project>/app/.
245
+ var parentDir = Path.GetDirectoryName(
246
+ baseDir.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar))
247
+ ?? baseDir;
248
+
249
+ // Candidate app directories: sibling of bin/ first, then directly under baseDir.
250
+ var appDirCandidates = new[]
251
+ {
252
+ Path.Combine(parentDir, "app"),
253
+ Path.Combine(parentDir, "App"),
254
+ Path.Combine(baseDir, "app"),
255
+ Path.Combine(baseDir, "App"),
256
+ };
257
+
258
+ string packageJsonPath = null;
259
+ string resolvedBaseDir = null;
260
+ foreach (var dir in appDirCandidates)
261
+ {
262
+ var candidate = Path.Combine(dir, "package.json");
263
+ if (File.Exists(candidate))
264
+ {
265
+ packageJsonPath = candidate;
266
+ resolvedBaseDir = dir;
267
+ break;
268
+ }
269
+ }
270
+
271
+ // Also accept package.json at the project root (parent of bin/).
272
+ if (packageJsonPath == null && File.Exists(Path.Combine(parentDir, "package.json")))
273
+ {
274
+ packageJsonPath = Path.Combine(parentDir, "package.json");
275
+ resolvedBaseDir = parentDir;
276
+ }
277
+
278
+ string Fallback() =>
279
+ appDirCandidates
280
+ .SelectMany(d => new[] { Path.Combine(d, "bundle.js"), Path.Combine(d, "bundle.mjs") })
281
+ .FirstOrDefault(File.Exists);
282
+
283
+ if (packageJsonPath == null)
284
+ return Fallback();
285
+
286
+ try
287
+ {
288
+ var config = ParsePackageConfig(packageJsonPath);
289
+ if (!string.IsNullOrWhiteSpace(config.WindowsMain))
290
+ {
291
+ var p = ResolveScriptPath(resolvedBaseDir, config.WindowsMain);
292
+ if (p != null) return p;
293
+ }
294
+ if (!string.IsNullOrWhiteSpace(config.Main))
295
+ {
296
+ var p = ResolveScriptPath(resolvedBaseDir, config.Main);
297
+ if (p != null) return p;
298
+ }
299
+ }
300
+ catch { }
301
+
302
+ return Fallback();
303
+ }
304
+
305
+ private static RuntimePackageConfig ParsePackageConfig(string packageJsonPath)
306
+ {
307
+ using var doc = JsonDocument.Parse(File.ReadAllText(packageJsonPath));
308
+ var config = new RuntimePackageConfig();
309
+ if (doc.RootElement.TryGetProperty("main", out var main) && main.ValueKind == JsonValueKind.String)
310
+ config.Main = main.GetString();
311
+ if (doc.RootElement.TryGetProperty("windows", out var win) && win.ValueKind == JsonValueKind.Object &&
312
+ win.TryGetProperty("main", out var winMain) && winMain.ValueKind == JsonValueKind.String)
313
+ config.WindowsMain = winMain.GetString();
314
+ return config;
315
+ }
316
+
317
+ private static string ResolveScriptPath(string baseDir, string scriptPath)
318
+ {
319
+ if (string.IsNullOrWhiteSpace(scriptPath)) return null;
320
+ var normalized = scriptPath.Replace('/', Path.DirectorySeparatorChar);
321
+ foreach (var candidate in new[] { normalized, normalized + ".js", normalized + ".mjs" })
322
+ {
323
+ var direct = Path.IsPathRooted(candidate) ? candidate : Path.Combine(baseDir, candidate);
324
+ if (File.Exists(direct)) return direct;
325
+ var appLower = Path.Combine(baseDir, "app", candidate);
326
+ if (File.Exists(appLower)) return appLower;
327
+ var appUpper = Path.Combine(baseDir, "App", candidate);
328
+ if (File.Exists(appUpper)) return appUpper;
329
+ }
330
+ return null;
331
+ }
332
+
333
+ /// Returns the last JavaScript error (message + stack trace) captured during
334
+ /// script execution, or null if no error was recorded since the last call.
335
+ public string GetLastJsError()
336
+ {
337
+ if (!_initialized) return null;
338
+ IntPtr ptr = IntPtr.Zero;
339
+ try
340
+ {
341
+ ptr = runtime_get_last_js_error();
342
+ return ptr == IntPtr.Zero ? null : Marshal.PtrToStringUTF8(ptr);
343
+ }
344
+ catch { return null; }
345
+ finally
346
+ {
347
+ if (ptr != IntPtr.Zero) runtime_free_js_error(ptr);
348
+ }
349
+ }
350
+
351
+ public void Dispose()
352
+ {
353
+ if (!_initialized) return;
354
+ runtime_deinit(_runtime);
355
+ _runtime = 0;
356
+ _initialized = false;
357
+ }
358
+ }
359
+ }