@nativescript/windows 0.1.0-alpha.8 → 0.1.0-alpha.80
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/build.ps1 +44 -2
- package/framework/__PROJECT_NAME__/App.xaml.cs +67 -22
- package/framework/__PROJECT_NAME__/Assets/SplashScreen.png +0 -0
- package/framework/__PROJECT_NAME__/Assets/Square150x150Logo.png +0 -0
- package/framework/__PROJECT_NAME__/Assets/Square44x44Logo.png +0 -0
- package/framework/__PROJECT_NAME__/Assets/StoreLogo.png +0 -0
- package/framework/__PROJECT_NAME__/Assets/Wide310x150Logo.png +0 -0
- package/framework/__PROJECT_NAME__/CrashDiagnostics.cs +262 -66
- package/framework/__PROJECT_NAME__/Directory.Build.props +15 -0
- package/framework/__PROJECT_NAME__/Directory.Build.targets +153 -0
- package/framework/__PROJECT_NAME__/Package.appxmanifest +2 -5
- package/framework/__PROJECT_NAME__/RuntimeHost.cs +97 -10
- package/framework/__PROJECT_NAME__/__PROJECT_NAME__.csproj +85 -12
- package/framework/dotnet-bridge/BinaryProtocol.cs +145 -0
- package/framework/dotnet-bridge/Bridge.BinaryDispatch.cs +216 -0
- package/framework/dotnet-bridge/Bridge.Dispatch.cs +468 -0
- package/framework/dotnet-bridge/Bridge.JsDelegate.cs +96 -0
- package/framework/dotnet-bridge/Bridge.TaskHelper.cs +207 -0
- package/framework/dotnet-bridge/Bridge.cs +402 -263
- package/framework/dotnet-bridge/DispatchTypes.cs +317 -0
- package/framework/dotnet-bridge/DotNetBridge.csproj +7 -1
- 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/framework/tools/dotnet-tool-arm64.exe +0 -0
- package/framework/tools/dotnet-tool-x64.exe +0 -0
- package/framework/tools/dotnet-tool.exe +0 -0
- package/package.json +19 -19
|
@@ -0,0 +1,153 @@
|
|
|
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
|
+
<!-- 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" Condition="'$(MSBuildRuntimeType)' != 'Core'">
|
|
10
|
+
<ParameterGroup>
|
|
11
|
+
<SourceManifest ParameterType="System.String" Required="true" />
|
|
12
|
+
<TargetManifest ParameterType="System.String" Required="true" />
|
|
13
|
+
</ParameterGroup>
|
|
14
|
+
<Task>
|
|
15
|
+
<Reference Include="System.Core" />
|
|
16
|
+
<Reference Include="System.Xml" />
|
|
17
|
+
<Reference Include="System.Xml.Linq" />
|
|
18
|
+
<Using Namespace="System" />
|
|
19
|
+
<Using Namespace="System.IO" />
|
|
20
|
+
<Using Namespace="System.Linq" />
|
|
21
|
+
<Using Namespace="System.Xml.Linq" />
|
|
22
|
+
<Code Type="Fragment" Language="cs"><![CDATA[
|
|
23
|
+
try {
|
|
24
|
+
if (!File.Exists(SourceManifest)) { Log.LogMessage(MessageImportance.Low, "No source manifest found: " + SourceManifest); return true; }
|
|
25
|
+
if (!File.Exists(TargetManifest)) { Log.LogMessage(MessageImportance.Low, "No target manifest found: " + TargetManifest); return true; }
|
|
26
|
+
XDocument src = XDocument.Load(SourceManifest);
|
|
27
|
+
XDocument dest = XDocument.Load(TargetManifest);
|
|
28
|
+
|
|
29
|
+
Func<XElement, XElement, bool> mergeElement = null;
|
|
30
|
+
mergeElement = (srcElem, destParent) => {
|
|
31
|
+
XElement match = destParent.Elements().FirstOrDefault(c => c.Name.LocalName == srcElem.Name.LocalName);
|
|
32
|
+
if (match == null) {
|
|
33
|
+
destParent.Add(new XElement(srcElem));
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
// copy/overwrite attributes
|
|
37
|
+
foreach (var a in srcElem.Attributes()) { match.SetAttributeValue(a.Name, a.Value); }
|
|
38
|
+
// merge children
|
|
39
|
+
foreach (var child in srcElem.Elements()) {
|
|
40
|
+
// skip if identical child exists
|
|
41
|
+
bool exists = match.Elements().Any(mc => mc.Name.LocalName == child.Name.LocalName && mc.ToString() == child.ToString());
|
|
42
|
+
if (exists) { continue; }
|
|
43
|
+
// try to find same-named child to merge into
|
|
44
|
+
XElement matchChild = match.Elements().FirstOrDefault(mc => mc.Name.LocalName == child.Name.LocalName);
|
|
45
|
+
if (matchChild != null) { mergeElement(child, matchChild); } else { match.Add(new XElement(child)); }
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Merge VisualElements (common case) into the Application node
|
|
51
|
+
var srcVisuals = src.Descendants().Where(e => e.Name.LocalName == "VisualElements");
|
|
52
|
+
foreach (var ve in srcVisuals) {
|
|
53
|
+
var destApp = dest.Descendants().FirstOrDefault(e => e.Name.LocalName == "Application");
|
|
54
|
+
if (destApp == null) { dest.Root.Add(new XElement(ve)); }
|
|
55
|
+
else { mergeElement(ve, destApp); }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Merge Capabilities (if present)
|
|
59
|
+
var srcCaps = src.Descendants().Where(e => e.Name.LocalName == "Capabilities");
|
|
60
|
+
foreach (var cap in srcCaps) {
|
|
61
|
+
var destCaps = dest.Descendants().FirstOrDefault(e => e.Name.LocalName == "Capabilities");
|
|
62
|
+
if (destCaps == null) { dest.Root.Add(new XElement(cap)); }
|
|
63
|
+
else { mergeElement(cap, destCaps); }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Merge other top-level sections present in src (e.g., Extensions) by local-name
|
|
67
|
+
foreach (var top in src.Root.Elements()) {
|
|
68
|
+
if (top.Name.LocalName == "Dependencies" || top.Name.LocalName == "Applications") { continue; }
|
|
69
|
+
var existing = dest.Root.Elements().FirstOrDefault(e => e.Name.LocalName == top.Name.LocalName);
|
|
70
|
+
if (existing == null) { dest.Root.Add(new XElement(top)); }
|
|
71
|
+
else {
|
|
72
|
+
// merge children of this section
|
|
73
|
+
foreach (var child in top.Elements()) {
|
|
74
|
+
bool exists = existing.Elements().Any(ec => ec.Name.LocalName == child.Name.LocalName && ec.ToString() == child.ToString());
|
|
75
|
+
if (!exists) { existing.Add(new XElement(child)); }
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
dest.Save(TargetManifest);
|
|
81
|
+
Log.LogMessage(MessageImportance.High, $"Merged manifest from {SourceManifest} into {TargetManifest}");
|
|
82
|
+
return true;
|
|
83
|
+
} catch (Exception ex) { Log.LogErrorFromException(ex); return false; }
|
|
84
|
+
]]></Code>
|
|
85
|
+
</Task>
|
|
86
|
+
</UsingTask>
|
|
87
|
+
|
|
88
|
+
<Target Name="MergeAppResourcesManifest" AfterTargets="ApplyManifestOverrides" Condition="Exists('$(MSBuildProjectDirectory)\Package.appxmanifest') and '$(MSBuildRuntimeType)' != 'Core'">
|
|
89
|
+
<PropertyGroup>
|
|
90
|
+
<_AppResourcesManifest>$(MSBuildProjectDirectory)\App_Resources\Windows\Package.appxmanifest</_AppResourcesManifest>
|
|
91
|
+
<!-- Allow CLI or callers to override the source manifest via MSBuild property 'AppResourcesManifestPath' -->
|
|
92
|
+
<_AppResourcesManifest Condition="'$(AppResourcesManifestPath)' != ''">$(AppResourcesManifestPath)</_AppResourcesManifest>
|
|
93
|
+
<!-- Fallback template manifest name (no '.partial' suffix) -->
|
|
94
|
+
<_PartialManifest>$(MSBuildProjectDirectory)\Package.appxmanifest</_PartialManifest>
|
|
95
|
+
</PropertyGroup>
|
|
96
|
+
<Message Text="Merging app manifest (if present) into generated Package.appxmanifest (app wins)" Importance="Low" />
|
|
97
|
+
<MergeAppxManifest SourceManifest="$([System.IO.File]::Exists('$(_AppResourcesManifest)') ? '$(_AppResourcesManifest)' : '$(_PartialManifest)')" TargetManifest="$(MSBuildProjectDirectory)\Package.appxmanifest" Condition=" $([System.IO.File]::Exists('$(_AppResourcesManifest)')) Or $([System.IO.File]::Exists('$(_PartialManifest)')) " />
|
|
98
|
+
</Target>
|
|
99
|
+
|
|
100
|
+
<Target Name="ApplyManifestOverrides" BeforeTargets="BeforeBuild" Condition="Exists('$(MSBuildProjectDirectory)\Package.appxmanifest')">
|
|
101
|
+
<Message Text="Applying manifest overrides (VisualElements, logos, splash) via XmlPoke..." Importance="High" />
|
|
102
|
+
|
|
103
|
+
<!-- DisplayName -->
|
|
104
|
+
<XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
|
|
105
|
+
Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@DisplayName"
|
|
106
|
+
Value="$(AppDisplayName)"
|
|
107
|
+
Condition="'$(AppDisplayName)' != ''" />
|
|
108
|
+
|
|
109
|
+
<!-- Description -->
|
|
110
|
+
<XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
|
|
111
|
+
Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@Description"
|
|
112
|
+
Value="$(AppDescription)"
|
|
113
|
+
Condition="'$(AppDescription)' != ''" />
|
|
114
|
+
|
|
115
|
+
<!-- Logos -->
|
|
116
|
+
<XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
|
|
117
|
+
Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@Square150x150Logo"
|
|
118
|
+
Value="$(Square150x150Logo)"
|
|
119
|
+
Condition="'$(Square150x150Logo)' != ''" />
|
|
120
|
+
|
|
121
|
+
<XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
|
|
122
|
+
Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@Square44x44Logo"
|
|
123
|
+
Value="$(Square44x44Logo)"
|
|
124
|
+
Condition="'$(Square44x44Logo)' != ''" />
|
|
125
|
+
|
|
126
|
+
<XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
|
|
127
|
+
Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/*[local-name()='DefaultTile']/@Wide310x150Logo"
|
|
128
|
+
Value="$(Wide310x150Logo)"
|
|
129
|
+
Condition="'$(Wide310x150Logo)' != ''" />
|
|
130
|
+
|
|
131
|
+
<XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
|
|
132
|
+
Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@StoreLogo"
|
|
133
|
+
Value="$(StoreLogo)"
|
|
134
|
+
Condition="'$(StoreLogo)' != ''" />
|
|
135
|
+
|
|
136
|
+
<XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
|
|
137
|
+
Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@LockScreenLogo"
|
|
138
|
+
Value="$(LockScreenLogo)"
|
|
139
|
+
Condition="'$(LockScreenLogo)' != ''" />
|
|
140
|
+
|
|
141
|
+
<!-- BackgroundColor and SplashScreen image -->
|
|
142
|
+
<XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
|
|
143
|
+
Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/@BackgroundColor"
|
|
144
|
+
Value="$(SplashBackgroundColor)"
|
|
145
|
+
Condition="'$(SplashBackgroundColor)' != ''" />
|
|
146
|
+
|
|
147
|
+
<XmlPoke XmlInputPath="$(MSBuildProjectDirectory)\Package.appxmanifest"
|
|
148
|
+
Query="/*[local-name()='Package']/*[local-name()='Applications']/*[local-name()='Application']/*[local-name()='VisualElements']/*[local-name()='SplashScreen']/@Image"
|
|
149
|
+
Value="$(SplashImage)"
|
|
150
|
+
Condition="'$(SplashImage)' != ''" />
|
|
151
|
+
|
|
152
|
+
</Target>
|
|
153
|
+
</Project>
|
|
@@ -2,17 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
<Package
|
|
4
4
|
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
|
5
|
-
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
|
6
5
|
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
|
7
|
-
IgnorableNamespaces="uap
|
|
6
|
+
IgnorableNamespaces="uap">
|
|
8
7
|
|
|
9
8
|
<Identity
|
|
10
9
|
Name="__APP_IDENTIFIER__"
|
|
11
10
|
Publisher="CN=__PROJECT_NAME__"
|
|
12
11
|
Version="1.0.0.0" />
|
|
13
12
|
|
|
14
|
-
<mp:PhoneIdentity PhoneProductId="__APP_IDENTIFIER__" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
|
15
|
-
|
|
16
13
|
<Properties>
|
|
17
14
|
<DisplayName>__PROJECT_NAME__</DisplayName>
|
|
18
15
|
<PublisherDisplayName>__PROJECT_NAME__</PublisherDisplayName>
|
|
@@ -24,7 +21,7 @@
|
|
|
24
21
|
</Dependencies>
|
|
25
22
|
|
|
26
23
|
<Resources>
|
|
27
|
-
<Resource Language="
|
|
24
|
+
<Resource Language="en-US"/>
|
|
28
25
|
</Resources>
|
|
29
26
|
|
|
30
27
|
<Applications>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
2
3
|
using System.IO;
|
|
4
|
+
using System.Linq;
|
|
3
5
|
using System.Runtime.InteropServices;
|
|
4
6
|
using System.Text.Json;
|
|
5
7
|
|
|
@@ -26,6 +28,41 @@ namespace __PROJECT_NAME__
|
|
|
26
28
|
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_install_ctrlc_handler))]
|
|
27
29
|
private static extern void runtime_install_ctrlc_handler(int exitCode);
|
|
28
30
|
|
|
31
|
+
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_set_local_folder))]
|
|
32
|
+
private static extern void runtime_set_local_folder([MarshalAs(UnmanagedType.LPUTF8Str)] string localFolder);
|
|
33
|
+
|
|
34
|
+
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_get_last_js_error))]
|
|
35
|
+
private static extern IntPtr runtime_get_last_js_error();
|
|
36
|
+
|
|
37
|
+
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_free_js_error))]
|
|
38
|
+
private static extern void runtime_free_js_error(IntPtr ptr);
|
|
39
|
+
|
|
40
|
+
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_has_devtools))]
|
|
41
|
+
private static extern bool runtime_has_devtools();
|
|
42
|
+
|
|
43
|
+
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_pump_timers))]
|
|
44
|
+
private static extern void runtime_pump_timers();
|
|
45
|
+
|
|
46
|
+
#if DEBUG
|
|
47
|
+
[DllImport(NativeScriptLibrary, EntryPoint = nameof(ns_set_log_to_console))]
|
|
48
|
+
private static extern int ns_set_log_to_console(int enabled);
|
|
49
|
+
|
|
50
|
+
public static bool TrySetLogToConsole(bool enabled)
|
|
51
|
+
{
|
|
52
|
+
try { return ns_set_log_to_console(enabled ? 1 : 0) == 1; }
|
|
53
|
+
catch { return false; }
|
|
54
|
+
}
|
|
55
|
+
#else
|
|
56
|
+
public static bool TrySetLogToConsole(bool enabled) => false;
|
|
57
|
+
#endif
|
|
58
|
+
|
|
59
|
+
public void PumpTimers()
|
|
60
|
+
{
|
|
61
|
+
if (!_initialized) return;
|
|
62
|
+
try { runtime_pump_timers(); }
|
|
63
|
+
catch { }
|
|
64
|
+
}
|
|
65
|
+
|
|
29
66
|
#if DEBUG
|
|
30
67
|
[DllImport(NativeScriptLibrary, EntryPoint = nameof(runtime_devtools_start))]
|
|
31
68
|
private static extern IntPtr runtime_devtools_start(long runtime, ushort port);
|
|
@@ -38,9 +75,11 @@ namespace __PROJECT_NAME__
|
|
|
38
75
|
|
|
39
76
|
public string DevtoolsFrontendUrl { get; private set; }
|
|
40
77
|
|
|
78
|
+
private bool _devtoolsAvailable;
|
|
79
|
+
|
|
41
80
|
public void PumpDevtools()
|
|
42
81
|
{
|
|
43
|
-
if (!_initialized) return;
|
|
82
|
+
if (!_initialized || !_devtoolsAvailable) return;
|
|
44
83
|
try { runtime_devtools_pump(_runtime); }
|
|
45
84
|
catch (Exception ex)
|
|
46
85
|
{
|
|
@@ -50,6 +89,7 @@ namespace __PROJECT_NAME__
|
|
|
50
89
|
|
|
51
90
|
private void StartDevtoolsSafely()
|
|
52
91
|
{
|
|
92
|
+
if (!runtime_has_devtools()) return;
|
|
53
93
|
IntPtr urlPtr = IntPtr.Zero;
|
|
54
94
|
try
|
|
55
95
|
{
|
|
@@ -60,7 +100,10 @@ namespace __PROJECT_NAME__
|
|
|
60
100
|
? $"devtools://devtools/bundled/inspector.html?ws={wsUrl.Replace("ws://", "")}"
|
|
61
101
|
: null;
|
|
62
102
|
if (DevtoolsFrontendUrl != null)
|
|
103
|
+
{
|
|
104
|
+
_devtoolsAvailable = true;
|
|
63
105
|
System.Diagnostics.Debug.WriteLine($"[NativeScript DevTools] {DevtoolsFrontendUrl}");
|
|
106
|
+
}
|
|
64
107
|
}
|
|
65
108
|
catch (Exception ex)
|
|
66
109
|
{
|
|
@@ -82,8 +125,10 @@ namespace __PROJECT_NAME__
|
|
|
82
125
|
if (_initialized) return;
|
|
83
126
|
AttachConsole(ATTACH_PARENT_PROCESS);
|
|
84
127
|
runtime_install_ctrlc_handler(0);
|
|
128
|
+
runtime_set_local_folder(Windows.Storage.ApplicationData.Current.LocalFolder.Path);
|
|
85
129
|
_runtime = runtime_init(AppContext.BaseDirectory);
|
|
86
130
|
#if DEBUG
|
|
131
|
+
TrySetLogToConsole(true);
|
|
87
132
|
if (ConsumeDebugBreakMarker())
|
|
88
133
|
StartDevtoolsSafely();
|
|
89
134
|
#endif
|
|
@@ -117,16 +162,38 @@ namespace __PROJECT_NAME__
|
|
|
117
162
|
throw new InvalidOperationException("Runtime must be initialized before running scripts.");
|
|
118
163
|
|
|
119
164
|
var entryPath = ResolveEntryScriptPath();
|
|
120
|
-
|
|
121
|
-
try
|
|
165
|
+
if (entryPath == null)
|
|
122
166
|
{
|
|
123
|
-
|
|
167
|
+
System.Diagnostics.Debug.WriteLine("[NativeScript Runtime] No entry script found — bundle missing from app directory.");
|
|
168
|
+
return;
|
|
124
169
|
}
|
|
125
|
-
|
|
170
|
+
|
|
171
|
+
var dir = Path.GetDirectoryName(Path.GetFullPath(entryPath));
|
|
172
|
+
var chunks = new List<string>();
|
|
173
|
+
foreach (var chunkName in new[] { "runtime.js", "vendor.js" })
|
|
174
|
+
{
|
|
175
|
+
var chunkPath = Path.Combine(dir, chunkName);
|
|
176
|
+
if (File.Exists(chunkPath) &&
|
|
177
|
+
!string.Equals(chunkPath, Path.GetFullPath(entryPath), StringComparison.OrdinalIgnoreCase))
|
|
178
|
+
{
|
|
179
|
+
chunks.Add(chunkPath);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
chunks.Add(entryPath);
|
|
183
|
+
|
|
184
|
+
foreach (var scriptPath in chunks)
|
|
126
185
|
{
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
186
|
+
var script = File.ReadAllText(Path.GetFullPath(scriptPath));
|
|
187
|
+
try
|
|
188
|
+
{
|
|
189
|
+
runtime_runscript(_runtime, script, Path.GetFileName(scriptPath));
|
|
190
|
+
}
|
|
191
|
+
catch (Exception ex)
|
|
192
|
+
{
|
|
193
|
+
CrashDiagnostics.WriteExceptionReport("RuntimeHost.RunMainScript", ex, "Script=" + scriptPath);
|
|
194
|
+
System.Diagnostics.Debug.WriteLine($"[NativeScript Runtime] Script execution failed ({scriptPath}): {ex}");
|
|
195
|
+
throw;
|
|
196
|
+
}
|
|
130
197
|
}
|
|
131
198
|
}
|
|
132
199
|
|
|
@@ -174,7 +241,9 @@ namespace __PROJECT_NAME__
|
|
|
174
241
|
}
|
|
175
242
|
|
|
176
243
|
string Fallback() =>
|
|
177
|
-
appDirCandidates
|
|
244
|
+
appDirCandidates
|
|
245
|
+
.SelectMany(d => new[] { Path.Combine(d, "bundle.js"), Path.Combine(d, "bundle.mjs") })
|
|
246
|
+
.FirstOrDefault(File.Exists);
|
|
178
247
|
|
|
179
248
|
if (packageJsonPath == null)
|
|
180
249
|
return Fallback();
|
|
@@ -214,7 +283,7 @@ namespace __PROJECT_NAME__
|
|
|
214
283
|
{
|
|
215
284
|
if (string.IsNullOrWhiteSpace(scriptPath)) return null;
|
|
216
285
|
var normalized = scriptPath.Replace('/', Path.DirectorySeparatorChar);
|
|
217
|
-
foreach (var candidate in new[] { normalized, normalized + ".js" })
|
|
286
|
+
foreach (var candidate in new[] { normalized, normalized + ".js", normalized + ".mjs" })
|
|
218
287
|
{
|
|
219
288
|
var direct = Path.IsPathRooted(candidate) ? candidate : Path.Combine(baseDir, candidate);
|
|
220
289
|
if (File.Exists(direct)) return direct;
|
|
@@ -226,6 +295,24 @@ namespace __PROJECT_NAME__
|
|
|
226
295
|
return null;
|
|
227
296
|
}
|
|
228
297
|
|
|
298
|
+
/// Returns the last JavaScript error (message + stack trace) captured during
|
|
299
|
+
/// script execution, or null if no error was recorded since the last call.
|
|
300
|
+
public string GetLastJsError()
|
|
301
|
+
{
|
|
302
|
+
if (!_initialized) return null;
|
|
303
|
+
IntPtr ptr = IntPtr.Zero;
|
|
304
|
+
try
|
|
305
|
+
{
|
|
306
|
+
ptr = runtime_get_last_js_error();
|
|
307
|
+
return ptr == IntPtr.Zero ? null : Marshal.PtrToStringUTF8(ptr);
|
|
308
|
+
}
|
|
309
|
+
catch { return null; }
|
|
310
|
+
finally
|
|
311
|
+
{
|
|
312
|
+
if (ptr != IntPtr.Zero) runtime_free_js_error(ptr);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
229
316
|
public void Dispose()
|
|
230
317
|
{
|
|
231
318
|
if (!_initialized) return;
|
|
@@ -25,6 +25,10 @@
|
|
|
25
25
|
<NSLibPlatform Condition="'$(Platform)' != ''">$(Platform)</NSLibPlatform>
|
|
26
26
|
<NSLibPlatform Condition="'$(NSLibPlatform)' == '' and '$(RuntimeIdentifier)' != ''">$([System.Text.RegularExpressions.Regex]::Replace('$(RuntimeIdentifier)','^win-',''))</NSLibPlatform>
|
|
27
27
|
<NSLibPlatform Condition="'$(NSLibPlatform)' == ''">x64</NSLibPlatform>
|
|
28
|
+
<!-- Windows SDK .NET runtime pack location (resolved from NuGet cache) -->
|
|
29
|
+
<_WinSdkNetRefPkg>$(NuGetPackageRoot)microsoft.windows.sdk.net.ref</_WinSdkNetRefPkg>
|
|
30
|
+
<_WinSdkNetRefVer Condition="Exists('$(_WinSdkNetRefPkg)\10.0.26100.57')">10.0.26100.57</_WinSdkNetRefVer>
|
|
31
|
+
<_WinSdkNetRefLib Condition="'$(_WinSdkNetRefVer)' != ''">$(_WinSdkNetRefPkg)\$(_WinSdkNetRefVer)\lib\net8.0</_WinSdkNetRefLib>
|
|
28
32
|
</PropertyGroup>
|
|
29
33
|
|
|
30
34
|
<ItemGroup>
|
|
@@ -41,6 +45,29 @@
|
|
|
41
45
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
42
46
|
</Content>
|
|
43
47
|
|
|
48
|
+
<!-- UWP logo/splash assets required for Add-AppxPackage -Register -->
|
|
49
|
+
<Content Include="Assets\**\*" Condition="Exists('Assets')">
|
|
50
|
+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
51
|
+
</Content>
|
|
52
|
+
|
|
53
|
+
<!-- Windows SDK .NET runtime pack assemblies — required when the dotnet workload
|
|
54
|
+
is not installed; copied from the NuGet package cache. -->
|
|
55
|
+
<Content Include="$(_WinSdkNetRefLib)\Microsoft.Windows.UI.Xaml.dll"
|
|
56
|
+
Condition="'$(_WinSdkNetRefLib)' != '' and Exists('$(_WinSdkNetRefLib)\Microsoft.Windows.UI.Xaml.dll')">
|
|
57
|
+
<Link>Microsoft.Windows.UI.Xaml.dll</Link>
|
|
58
|
+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
59
|
+
</Content>
|
|
60
|
+
<Content Include="$(_WinSdkNetRefLib)\WinRT.Runtime.dll"
|
|
61
|
+
Condition="'$(_WinSdkNetRefLib)' != '' and Exists('$(_WinSdkNetRefLib)\WinRT.Runtime.dll')">
|
|
62
|
+
<Link>WinRT.Runtime.dll</Link>
|
|
63
|
+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
64
|
+
</Content>
|
|
65
|
+
<Content Include="$(_WinSdkNetRefLib)\Microsoft.Windows.SDK.NET.dll"
|
|
66
|
+
Condition="'$(_WinSdkNetRefLib)' != '' and Exists('$(_WinSdkNetRefLib)\Microsoft.Windows.SDK.NET.dll')">
|
|
67
|
+
<Link>Microsoft.Windows.SDK.NET.dll</Link>
|
|
68
|
+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
69
|
+
</Content>
|
|
70
|
+
|
|
44
71
|
<!-- Debug: devtools-enabled runtime DLL (platform fallback via NSLibPlatform) -->
|
|
45
72
|
<Content Include="$(NSWindowsRoot)\libs\devtools\$(NSLibPlatform)\nativescript.dll"
|
|
46
73
|
Condition="'$(Configuration)' == 'Debug' and Exists('$(NSWindowsRoot)\libs\devtools\$(NSLibPlatform)\nativescript.dll')">
|
|
@@ -55,21 +82,12 @@
|
|
|
55
82
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
56
83
|
</Content>
|
|
57
84
|
|
|
58
|
-
<!-- .NET bridge — published on first build by the target below; enables ns.dotnet.*
|
|
59
|
-
APIs from JavaScript. Must land at dotnet-bridge\publish\ relative to the
|
|
60
|
-
executable so the Rust runtime can locate DotNetBridge.dll via
|
|
61
|
-
AppContext.BaseDirectory. Condition guards against a missing source tree. -->
|
|
62
|
-
<Content Include="$(NSWindowsRoot)\dotnet-bridge\publish\**\*"
|
|
63
|
-
Condition="Exists('$(NSWindowsRoot)\dotnet-bridge\publish')">
|
|
64
|
-
<Link>dotnet-bridge\publish\%(RecursiveDir)%(Filename)%(Extension)</Link>
|
|
65
|
-
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
66
|
-
</Content>
|
|
67
85
|
</ItemGroup>
|
|
68
86
|
|
|
69
87
|
<!--
|
|
70
|
-
Publishes DotNetBridge.dll before the app build
|
|
71
|
-
|
|
72
|
-
|
|
88
|
+
Publishes DotNetBridge.dll before the app build.
|
|
89
|
+
Inputs/Outputs make this incremental: MSBuild skips the Exec when DotNetBridge.dll
|
|
90
|
+
is already newer than both source files.
|
|
73
91
|
-->
|
|
74
92
|
<Target Name="PublishDotNetBridge"
|
|
75
93
|
BeforeTargets="Build"
|
|
@@ -81,6 +99,61 @@
|
|
|
81
99
|
<Exec Command="dotnet publish "$(NSWindowsRoot)\dotnet-bridge\DotNetBridge.csproj" -c Release -o "$(NSWindowsRoot)\dotnet-bridge\publish" --no-self-contained /nologo" />
|
|
82
100
|
</Target>
|
|
83
101
|
|
|
102
|
+
<!--
|
|
103
|
+
Copies the published bridge files to the output directory AFTER PublishDotNetBridge
|
|
104
|
+
runs, avoiding the MSBuild evaluation-order problem where Condition="Exists(...)"
|
|
105
|
+
on a static Content item is checked before the publish target creates the directory.
|
|
106
|
+
Must land at dotnet-bridge\publish\ relative to the EXE so the Rust runtime can
|
|
107
|
+
locate DotNetBridge.dll via AppContext.BaseDirectory.
|
|
108
|
+
-->
|
|
109
|
+
<Target Name="CopyDotNetBridge"
|
|
110
|
+
AfterTargets="PublishDotNetBridge"
|
|
111
|
+
BeforeTargets="Build"
|
|
112
|
+
Condition="Exists('$(NSWindowsRoot)\dotnet-bridge\publish')">
|
|
113
|
+
<ItemGroup>
|
|
114
|
+
<_DotNetBridgeFiles Include="$(NSWindowsRoot)\dotnet-bridge\publish\**\*" />
|
|
115
|
+
</ItemGroup>
|
|
116
|
+
<Copy SourceFiles="@(_DotNetBridgeFiles)"
|
|
117
|
+
DestinationFiles="@(_DotNetBridgeFiles->'$(OutDir)dotnet-bridge\%(RecursiveDir)%(Filename)%(Extension)')"
|
|
118
|
+
SkipUnchangedFiles="true" />
|
|
119
|
+
</Target>
|
|
120
|
+
|
|
121
|
+
<!-- Ensure bridge files are included in the final `dotnet publish` output. -->
|
|
122
|
+
<Target Name="CopyDotNetBridgeToPublishDir"
|
|
123
|
+
AfterTargets="Publish"
|
|
124
|
+
Condition="Exists('$(NSWindowsRoot)\dotnet-bridge\publish')">
|
|
125
|
+
<ItemGroup>
|
|
126
|
+
<_DotNetBridgePublishFiles Include="$(NSWindowsRoot)\dotnet-bridge\publish\**\*" />
|
|
127
|
+
</ItemGroup>
|
|
128
|
+
<Copy SourceFiles="@(_DotNetBridgePublishFiles)"
|
|
129
|
+
DestinationFiles="@(_DotNetBridgePublishFiles->'$(PublishDir)dotnet-bridge\%(RecursiveDir)%(Filename)%(Extension)')"
|
|
130
|
+
SkipUnchangedFiles="true" />
|
|
131
|
+
</Target>
|
|
132
|
+
|
|
133
|
+
<!-- Inject the bridge publish files as Content before Publish so `dotnet publish` includes them automatically -->
|
|
134
|
+
<Target Name="AddDotNetBridgeContent" BeforeTargets="Publish" Condition="Exists('$(NSWindowsRoot)\dotnet-bridge\publish')">
|
|
135
|
+
<ItemGroup>
|
|
136
|
+
<Content Include="$(NSWindowsRoot)\dotnet-bridge\publish\**\*">
|
|
137
|
+
<Link>dotnet-bridge\%(RecursiveDir)%(Filename)%(Extension)</Link>
|
|
138
|
+
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
139
|
+
</Content>
|
|
140
|
+
</ItemGroup>
|
|
141
|
+
</Target>
|
|
142
|
+
|
|
143
|
+
<!--
|
|
144
|
+
Wait for the `dotnet-tool` sentinel marker so Build/Publish don't race with
|
|
145
|
+
the external tool that publishes/copies DotNetBridge into the repo.
|
|
146
|
+
This polls for `dotnet-bridge/publish/.dotnet_tool_done` with a short timeout.
|
|
147
|
+
-->
|
|
148
|
+
<Target Name="WaitForDotNetToolDone" BeforeTargets="Build;Publish" Condition="Exists('$(NSWindowsRoot)\dotnet-bridge')">
|
|
149
|
+
<PropertyGroup>
|
|
150
|
+
<DotNetToolMarker>$(NSWindowsRoot)\dotnet-bridge\publish\.dotnet_tool_done</DotNetToolMarker>
|
|
151
|
+
<DotNetWaitTimeout>30</DotNetWaitTimeout>
|
|
152
|
+
</PropertyGroup>
|
|
153
|
+
<Message Text="[NativeScript] Waiting for dotnet-tool marker at $(DotNetToolMarker) (timeout $(DotNetWaitTimeout)s)..." Importance="high" />
|
|
154
|
+
<Exec Command="powershell -NoProfile -Command "$t=0; while(-not(Test-Path '$(DotNetToolMarker)') -and $t -lt $(DotNetWaitTimeout)) { Start-Sleep -Seconds 1; $t++; }; if(-not(Test-Path '$(DotNetToolMarker)')) { Write-Error 'dotnet-tool marker not found after timeout'; exit 1 };"" />
|
|
155
|
+
</Target>
|
|
156
|
+
|
|
84
157
|
<!-- Allow project-level Windows overrides: place App_Resources\Windows\app.csproj to extend/override generated settings -->
|
|
85
158
|
<Import Project="App_Resources\Windows\app.csproj" Condition="Exists('App_Resources\Windows\app.csproj')" />
|
|
86
159
|
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Buffers;
|
|
3
|
+
using System.Buffers.Binary;
|
|
4
|
+
using System.Text;
|
|
5
|
+
|
|
6
|
+
namespace NativeScriptBridge;
|
|
7
|
+
|
|
8
|
+
internal readonly struct HandleRef(int id)
|
|
9
|
+
{
|
|
10
|
+
public readonly int Id = id;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Carries a raw IUnknown/IInspectable pointer from a WinRT proxy (tag 0x0A).
|
|
14
|
+
// CoerceBin calls Marshal.GetObjectForIUnknown to create a managed RCW.
|
|
15
|
+
internal readonly struct WinRtRef(long ptr)
|
|
16
|
+
{
|
|
17
|
+
public readonly long Ptr = ptr;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
internal ref struct BinReader(ReadOnlySpan<byte> buf)
|
|
21
|
+
{
|
|
22
|
+
private readonly ReadOnlySpan<byte> _buf = buf;
|
|
23
|
+
private int _pos = 0;
|
|
24
|
+
|
|
25
|
+
public byte ReadByte() => _buf[_pos++];
|
|
26
|
+
|
|
27
|
+
public int ReadI32()
|
|
28
|
+
{
|
|
29
|
+
var v = BinaryPrimitives.ReadInt32LittleEndian(_buf[_pos..]);
|
|
30
|
+
_pos += 4;
|
|
31
|
+
return v;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public long ReadI64()
|
|
35
|
+
{
|
|
36
|
+
var v = BinaryPrimitives.ReadInt64LittleEndian(_buf[_pos..]);
|
|
37
|
+
_pos += 8;
|
|
38
|
+
return v;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public ushort ReadU16()
|
|
42
|
+
{
|
|
43
|
+
var v = BinaryPrimitives.ReadUInt16LittleEndian(_buf[_pos..]);
|
|
44
|
+
_pos += 2;
|
|
45
|
+
return v;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public double ReadF64()
|
|
49
|
+
{
|
|
50
|
+
var v = BinaryPrimitives.ReadDoubleLittleEndian(_buf[_pos..]);
|
|
51
|
+
_pos += 8;
|
|
52
|
+
return v;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public string ReadString16()
|
|
56
|
+
{
|
|
57
|
+
var len = ReadU16();
|
|
58
|
+
var s = Encoding.UTF8.GetString(_buf.Slice(_pos, len));
|
|
59
|
+
_pos += len;
|
|
60
|
+
// Intern so repeated method/type names reuse the same heap string.
|
|
61
|
+
// Eliminates the allocation on every subsequent warm-path call.
|
|
62
|
+
return string.Intern(s);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public object?[] ReadArgs()
|
|
66
|
+
{
|
|
67
|
+
var count = ReadByte();
|
|
68
|
+
if (count == 0) return [];
|
|
69
|
+
var args = new object?[count];
|
|
70
|
+
for (int i = 0; i < count; i++)
|
|
71
|
+
{
|
|
72
|
+
var tag = ReadByte();
|
|
73
|
+
args[i] = tag switch
|
|
74
|
+
{
|
|
75
|
+
0x00 => null,
|
|
76
|
+
0x01 => (object)false,
|
|
77
|
+
0x02 => (object)true,
|
|
78
|
+
0x03 => (object)ReadI32(),
|
|
79
|
+
0x04 => (object)ReadF64(),
|
|
80
|
+
0x05 => (object)ReadString16(),
|
|
81
|
+
0x06 => (object)new HandleRef(ReadI32()),
|
|
82
|
+
0x0A => (object)new WinRtRef(ReadI64()),
|
|
83
|
+
_ => null,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return args;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
internal ref struct BinWriter(ArrayBufferWriter<byte> buf)
|
|
91
|
+
{
|
|
92
|
+
private readonly ArrayBufferWriter<byte> _buf = buf;
|
|
93
|
+
|
|
94
|
+
public void WriteByte(byte b)
|
|
95
|
+
{
|
|
96
|
+
_buf.GetSpan(1)[0] = b;
|
|
97
|
+
_buf.Advance(1);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
public void WriteI32(int v)
|
|
101
|
+
{
|
|
102
|
+
BinaryPrimitives.WriteInt32LittleEndian(_buf.GetSpan(4), v);
|
|
103
|
+
_buf.Advance(4);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public void WriteU16(ushort v)
|
|
107
|
+
{
|
|
108
|
+
BinaryPrimitives.WriteUInt16LittleEndian(_buf.GetSpan(2), v);
|
|
109
|
+
_buf.Advance(2);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
public void WriteU32(uint v)
|
|
113
|
+
{
|
|
114
|
+
BinaryPrimitives.WriteUInt32LittleEndian(_buf.GetSpan(4), v);
|
|
115
|
+
_buf.Advance(4);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public void WriteI64(long v)
|
|
119
|
+
{
|
|
120
|
+
BinaryPrimitives.WriteInt64LittleEndian(_buf.GetSpan(8), v);
|
|
121
|
+
_buf.Advance(8);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public void WriteF64(double v)
|
|
125
|
+
{
|
|
126
|
+
BinaryPrimitives.WriteDoubleLittleEndian(_buf.GetSpan(8), v);
|
|
127
|
+
_buf.Advance(8);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
public void WriteString32(ReadOnlySpan<char> s)
|
|
131
|
+
{
|
|
132
|
+
var byteCount = Encoding.UTF8.GetByteCount(s);
|
|
133
|
+
WriteU32((uint)byteCount);
|
|
134
|
+
Encoding.UTF8.GetBytes(s, _buf.GetSpan(byteCount));
|
|
135
|
+
_buf.Advance(byteCount);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
public void WriteString16(ReadOnlySpan<char> s)
|
|
139
|
+
{
|
|
140
|
+
var byteCount = Encoding.UTF8.GetByteCount(s);
|
|
141
|
+
WriteU16((ushort)byteCount);
|
|
142
|
+
Encoding.UTF8.GetBytes(s, _buf.GetSpan(byteCount));
|
|
143
|
+
_buf.Advance(byteCount);
|
|
144
|
+
}
|
|
145
|
+
}
|