Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion content/best-practices/platform-file-split-or-not.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ Using platform files:

- `file.ios.ts`
- `file.android.ts`
- `file.windows.ts` (when targeting [Windows](/guide/windows/))

The advent of tree shaking and webpack builds does away with quite a bit of worry in this area however there's a few things to consider here.

## Conditional with tree shaking

When speaking of tree shaking ever since NativeScript 7, you've been able to use `__ANDROID__` or `global.isIOS` and anytime those are used as conditional splits in your code, only the applicable code for the platform that's being built would actually end up in your compiled code alleviating a lot of concern here.
When speaking of tree shaking ever since NativeScript 7, you've been able to use `__ANDROID__`, `__WINDOWS__` or `global.isIOS` and anytime those are used as conditional splits in your code, only the applicable code for the platform that's being built would actually end up in your compiled code alleviating a lot of concern here.

## Future maintenance

Expand Down
52 changes: 51 additions & 1 deletion content/configuration/nativescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default {
id: string = 'com.mycompany.myapp'
```

Controls the Application ID of your app, this setting can be overridden per platform via [ios.id](#ios-id) and [android.id](#android-id).
Controls the Application ID of your app, this setting can be overridden per platform via [ios.id](#ios-id), [android.id](#android-id) and [windows.id](#windows-id).

### main

Expand Down Expand Up @@ -163,6 +163,14 @@ ios: Object = {}

See [iOS Configuration Reference](#ios-configuration-reference)

### windows

```ts
windows: Object = {}
```

See [Windows Configuration Reference](#windows-configuration-reference)

### hooks

```ts
Expand Down Expand Up @@ -508,6 +516,48 @@ ios: {
}
```

## Windows Configuration Reference

::: warning Experimental
The Windows platform is experimental. See [Developing for Windows](/guide/windows/).
:::

### <span>windows.id</span>

```ts
windows.id: string = 'com.mycompany.myapp';
```

Controls the package identity name of your Windows app, this setting overrides the value set in [id](#id). The value is written to the `Name` attribute of the `<Identity>` element in the generated `Package.appxmanifest`, and the CLI uses it to find, install and remove the app package.

### windows.sourceProtect

```ts
windows.sourceProtect: boolean = true;
```

When enabled, **release** builds seal the bundled JavaScript into an encrypted `app.nsbundle` instead of shipping it as plain `.js` files. Defaults to `false`.

This can be overridden per build with `--source-protect` or `--no-source-protect`. The encryption key can be provided with `--source-protect-key-hex <key>` or the `NS_WINDOWS_BUNDLE_KEY` environment variable.

```ts
export default {
// ...
windows: {
sourceProtect: true,
},
} as NativeScriptConfig
```

### windows.phoneProductId / windows.phonePublisherId

```ts
windows.phoneProductId: string = '00000000-0000-0000-0000-000000000000';
windows.phonePublisherId: string = '00000000-0000-0000-0000-000000000000';
```

Values written to the `mp:PhoneIdentity` element of the generated `Package.appxmanifest`. When `phoneProductId` isn't set (or is empty/all zeros), the CLI generates a stable GUID derived from the app id. Can be overridden with `--phone-product-id` and `--phone-publisher-id`.

## Hooks Configuration Reference

```ts
Expand Down
9 changes: 8 additions & 1 deletion content/configuration/vite.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,8 @@ Additional env flags that are passed by the CLI automatically
- `--env.android` - `true` when running on Android
- `--env.ios` - `true` when running on iOS
- `--env.visionos` - `true` when running on visionOS
- `--env.platform=<platform>` - for specifying the platform to use. Can be `android`, `ios`, or `visionos`.
- `--env.windows` - `true` when running on Windows
- `--env.platform=<platform>` - for specifying the platform to use. Can be `android`, `ios`, `visionos`, or `windows`.
- `--env.hmr` - `true` when building with HMR enabled

## Global "magic" variables
Expand Down Expand Up @@ -397,6 +398,12 @@ We define a few useful globally available variables that you can use to alter lo
// we are running on an Apple platform
}
```
- `__WINDOWS__`, `true` when the platform is Windows
```ts
if (__WINDOWS__) {
// we are running on Windows
}
```

::: details The following variables are also defined, but are primarily intended to be used by NativeScript Core internally, or plugins that wish to use these.

Expand Down
10 changes: 9 additions & 1 deletion content/configuration/webpack.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ Additional env flags that are usually passed by the CLI automatically
- `--env.nativescriptLibPath` - path to the currently running CLI's library.
- `--env.android` - `true` when running on android
- `--env.ios` - `true` when running on ios
- `--env.platform=<platform>` - for specifying the platform to use. Can be `android` or `ios`, or a custom platform in the future.
- `--env.visionos` - `true` when running on visionOS
- `--env.windows` - `true` when running on Windows
- `--env.platform=<platform>` - for specifying the platform to use. Can be `android`, `ios`, `visionos`, `windows`, or a custom platform.
- `--env.hmr` - `true` when building with HMR enabled

## Global "magic" variables
Expand All @@ -121,6 +123,12 @@ We define a few useful globally available variables that you can use to alter lo
// we are running on iOS
}
```
- `__WINDOWS__` (also available as `global.isWindows`) - `true` when the platform is Windows
```ts
if (__WINDOWS__) {
// we are running on Windows
}
```

::: details The following variables are also defined, but are primarily intended to be used by NativeScript Core internally, or plugins that wish to use these.

Expand Down
1 change: 1 addition & 0 deletions content/guide/adding-native-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ ns native add java com.company.OtherAwesomeClass
1. You can also manually add native code to [App_Resources](/project-structure/app-resources):
- [Adding Java/Kotlin code to an application](/guide/native-code/android)
- [Adding ObjectiveC/Swift Code to an application](/guide/native-code/ios)
- [Adding Windows native code (C#, C++/WinRT, Win32) to an application](/guide/native-code/windows)
2. Optionally [generate TypeScript types for the added APIs](/guide/native-code/generate-typings)

Additionally, NativeScript also supports Jetpack Compose and SwiftUI through plugins.
Expand Down
2 changes: 2 additions & 0 deletions content/guide/cli-basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ Example output:
| 3 | iPhone 14 Pro | iOS | XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX | Emulator | Connected | Local |
```

On a Windows host, the local machine is also listed as a `Windows` device, which is the target used by `ns run windows` (see [Developing for Windows](/guide/windows/)).

## Setting the default package manager

To set the default package manager that the CLI uses (unless overridden in [nativescript.config.ts](/project-structure/nativescript-config#cli-packagemanager)):
Expand Down
63 changes: 61 additions & 2 deletions content/guide/debugging.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ contributors:
- rigor789
---

There are multiple ways to debug issues in your apps, starting with the simplest form using `console.logs`. For more complex issues, you may need to use an actual debugger, like Chrome DevTools, XCode developer tools and instruments or the Android Studio developer tools.
There are multiple ways to debug issues in your apps, starting with the simplest form using `console.logs`. For more complex issues, you may need to use an actual debugger, like Chrome DevTools, XCode developer tools and instruments, the Android Studio developer tools or Visual Studio on Windows.

## Console

Expand Down Expand Up @@ -41,7 +41,7 @@ console.timeEnd('myLabel')
To start a Chrome debugging session, run your app in debug mode:

```bash
ns debug android|ios
ns debug android|ios|windows
```

The `ns debug` command builds and deploys the app on a connected device or emulator, in case you have multiple devices available you will need to pick one from a list, or pass in the `--device <id>` from `ns devices`.
Expand Down Expand Up @@ -163,3 +163,62 @@ Since NativeScript follows a standard gradle/android application structure, you
- [Android Studio: Layout Inspector](https://developer.android.com/studio/debug/layout-inspector)
- [Android Studio: view Logcat logs](https://developer.android.com/studio/debug/am-logcat)
- [Androud Studio: Debug your app](https://developer.android.com/studio/debug#startdebug)

## Debugging on Windows

::: warning Experimental
The Windows platform is experimental. See [Developing for Windows](/guide/windows/).
:::

### Chrome DevTools

Start a debug session on the local machine with:

```bash
ns debug windows
```

The command builds, deploys and launches the app with the V8 inspector enabled. Once the inspector is listening, a URL is printed to the console:

```bash
# NativeScript Debugger started #
To start debugging, open the following URL in Chrome:
devtools://devtools/bundled/inspector.html?ws=127.0.0.1:43000
```

Open the printed URL in Google Chrome to attach to the debugger session. The inspector listens on port `43000` (iOS uses `41000` and Android `42000`), or the next free port if `43000` is taken.

Alternatively open `chrome://inspect` in Chrome, click **Configure...**, add `127.0.0.1:43000`, and select the app from the **Remote Target** list. Any other client that speaks the Chrome DevTools Protocol can connect to the same address.

The same options as on the other platforms are supported:

- `--debug-brk` - pauses on the first line of JavaScript until the debugger connects. The app waits up to 30 seconds for a debugger, then continues.
- `--start` - attaches to an app that is already running with the debugger enabled (started with `ns debug windows`), without restarting it.
- `--timeout` - number of seconds the CLI waits for the inspector to start. Default is 60 seconds.

`ns run windows` doesn't start the inspector, use `ns debug windows` instead.

The debugger, console, sources, CPU profiling and memory snapshots are provided by V8's inspector. Network requests made with `@nativescript/core` HTTP APIs are shown in the **Network** tab.

### Console output

`ns run windows` and `ns debug windows` stream the app's console output to your terminal. The output is also written to:

- the debugger output (visible in the Visual Studio **Output** window or [DebugView](https://learn.microsoft.com/sysinternals/downloads/debugview))
- `%LOCALAPPDATA%\Packages\<PackageFamilyName>\LocalState\console.log`

### Crash logs

When the app crashes, the runtime writes diagnostic files to the app's `LocalState` folder (`%LOCALAPPDATA%\Packages\<PackageFamilyName>\LocalState\`):

- `nativescript-crash.log` &mdash; unhandled JavaScript and XAML errors (also streamed to the terminal)
- `nativescript-panic.log` &mdash; internal runtime errors
- `nativescript-veh.log` &mdash; fatal native exceptions

In debug builds, an uncaught JavaScript error during startup shows a **NativeScript Runtime Error** dialog with the error details and the option to copy them or restart the app.

Some XAML errors terminate the process immediately (for example error `0xC000027B`) without reaching these logs. In that case check **Event Viewer › Windows Logs › Application**, or capture a crash dump with [ProcDump](https://learn.microsoft.com/sysinternals/downloads/procdump). See [Troubleshooting › Windows](/troubleshooting#windows).

### Debugging native code with Visual Studio

To debug native (C#, C++ or WinRT) code, run the app with `ns run windows`, then in [Visual Studio](https://visualstudio.microsoft.com/) use **Debug › Attach to Process...**, select your app's process, and choose the **Managed** and/or **Native** code types. You can also open the generated host project in `platforms/windows/<ProjectName>/` in Visual Studio to browse and set breakpoints in its code.
153 changes: 153 additions & 0 deletions content/guide/extending-classes-and-implementing-interfaces-windows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
---
title: Extending WinRT and .NET classes and implementing interfaces
description: Subclass WinRT and .NET classes and implement interfaces from JavaScript.
contributors:
- triniwiz
---

::: warning Experimental
The Windows platform is experimental. See [Developing for Windows](/guide/windows/).
:::

On Windows you can extend unsealed WinRT classes (for example WinUI's `Panel` or `Control`) and .NET classes (including your own [C# code](/guide/native-code/windows#adding-your-own-c-code)), and implement WinRT and .NET interfaces. When native code calls a member you override, your JavaScript runs. Members you don't override keep their native behavior.

## Extending classes

Extend a class with the `class` syntax:

```ts
class FixedPanel extends Microsoft.UI.Xaml.Controls.Panel {
constructor() {
super()
this.measures = 0
}

MeasureOverride(availableSize) {
this.measures++
return { Width: 120, Height: 40 }
}

ArrangeOverride(finalSize) {
return super.ArrangeOverride(finalSize)
}
}

const panel = new FixedPanel()
container.Children.Append(panel) // XAML now calls MeasureOverride/ArrangeOverride
```

Or call `extend` on the class, optionally passing a name first:

```ts
const FixedPanel = Microsoft.UI.Xaml.Controls.Panel.extend('FixedPanel', {
init() {
// called after construction, with the constructor arguments
},
MeasureOverride(availableSize) {
return { Width: 120, Height: 40 }
},
ArrangeOverride(finalSize) {
return this.super.ArrangeOverride(finalSize)
},
})
```

The same works for .NET classes:

```cs
// App_Resources/Windows/src/Animal.cs
namespace MyCompany.Native;

public class Animal
{
public Animal(string name) { Name = name; }
public string Name { get; }
public virtual string Speak() => "...";
public string Describe() => $"{Name} says {Speak()}";
}
```

```ts
class Cat extends MyCompany.Native.Animal {
Speak() {
return 'Meow'
}
}

console.log(new Cat('Tom').Describe()) // Tom says Meow
```

- Override methods and properties with their WinRT/.NET names. Override properties with `get`/`set` accessors.
- Constructor arguments passed to `super(...)` (or to `new` for classes made with `extend`) select and call the matching base constructor.
- `super.Member(...)` (or `this.super.Member(...)` in `extend`) calls the base implementation.
- You can override protected members and implement the abstract members of abstract classes.
- Fields you set on `this` are visible when native code calls your overrides, and `instanceof` works for your class and its native base classes.
- When native code hands an instance back to JavaScript (for example `panel.Children.GetAt(0)`), you get the same JavaScript object.
- Classes can be extended again, from JavaScript.

::: warning Sealed classes
Only unsealed classes can be extended. Most WinRT runtime classes, for example `Windows.Data.Json.JsonObject`, are **sealed**. A JavaScript subclass of a sealed class gets your JavaScript members, but native code never calls them.
:::

### TypeScript and `@NativeClass()`

Code written for Android and iOS works unchanged: `@NativeClass()` classes, TypeScript's ES5 output, and constructors ending with `return global.__native(this)` are all supported. On Windows the decorator isn't required.

```ts
@NativeClass()
class FixedPanel extends Microsoft.UI.Xaml.Controls.Panel {
MeasureOverride(availableSize: Windows.Foundation.Size) {
return { Width: 120, Height: 40 }
}
}
```

## Implementing interfaces

Implement an interface by passing its members to the interface constructor:

```ts
const calculator = new MyCompany.Native.ICalculator({
Compute(a, b) {
return a * b
},
get Name() {
return 'multiply'
},
})

MyCompany.Native.Runner.Run(calculator, 6, 7) // 42
```

To implement interfaces on a class, list them with `@Interfaces`, or with an `interfaces` key when using `extend`:

```ts
@Interfaces([Windows.Foundation.IStringable])
class Named extends System.Object {
ToString() {
return 'named'
}
}

const Stringable = Object.extend({
interfaces: [Windows.Foundation.IStringable],
ToString() {
return 'Hello from JavaScript'
},
})
```

## Lifetime

An instance of a JavaScript subclass is a JavaScript object together with the native object it drives. It is freed when neither your JavaScript nor native code references it.

As on Android, keep a reference to an instance that is only used from native code if its fields matter. If native code calls into an instance whose JavaScript object was garbage collected, a new JavaScript object of the same class is created for it, without the fields its constructor set. Instances of UI classes stay alive, with their fields, while they are in the visual tree.

## How it works

The runtime creates a .NET type for each subclass at runtime, deriving from the C#/WinRT projection of the base class (the way a C# subclass does). That type forwards the members you override, and the interface members you implement, to your JavaScript object. No build step or generated code is involved.

## Limitations

- Sealed classes can't be extended.
- JavaScript runs on the UI thread. Native code that calls an override on a background thread waits while it runs there, see [Multithreading](/guide/multithreading#windows).
Loading
Loading