diff --git a/Directory.Build.targets b/Directory.Build.targets
index cdfa0ed38f55..143f356e234a 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -125,4 +125,7 @@
+
+
+
diff --git a/src/Controls/samples/Controls.Sample/Maui.Controls.Sample.csproj b/src/Controls/samples/Controls.Sample/Maui.Controls.Sample.csproj
index 308ab6a0e930..f46f0840aa7c 100644
--- a/src/Controls/samples/Controls.Sample/Maui.Controls.Sample.csproj
+++ b/src/Controls/samples/Controls.Sample/Maui.Controls.Sample.csproj
@@ -77,6 +77,7 @@
+
diff --git a/src/Controls/samples/Controls.Sample/Resources/Raw/HybridSamplePage/scripts/HybridWebView.js b/src/Controls/samples/Controls.Sample/Resources/Raw/HybridSamplePage/scripts/HybridWebView.js
deleted file mode 100644
index 52d67172af49..000000000000
--- a/src/Controls/samples/Controls.Sample/Resources/Raw/HybridSamplePage/scripts/HybridWebView.js
+++ /dev/null
@@ -1,145 +0,0 @@
-window.HybridWebView = {
- "Init": function Init() {
- function DispatchHybridWebViewMessage(message) {
- const event = new CustomEvent("HybridWebViewMessageReceived", { detail: { message: message } });
- window.dispatchEvent(event);
- }
-
- if (window.chrome && window.chrome.webview) {
- // Windows WebView2
- window.chrome.webview.addEventListener('message', arg => {
- DispatchHybridWebViewMessage(arg.data);
- });
- }
- else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
- // iOS and MacCatalyst WKWebView
- window.external = {
- "receiveMessage": message => {
- DispatchHybridWebViewMessage(message);
- }
- };
- }
- else {
- // Android WebView
- window.addEventListener('message', arg => {
- DispatchHybridWebViewMessage(arg.data);
- });
- }
- },
-
- "SendRawMessage": function SendRawMessage(message) {
- window.HybridWebView.__SendMessageInternal('__RawMessage', message);
- },
-
- "InvokeDotNet": async function InvokeDotNetAsync(methodName, paramValues) {
- const body = {
- MethodName: methodName
- };
-
- if (typeof paramValues !== 'undefined') {
- if (!Array.isArray(paramValues)) {
- paramValues = [paramValues];
- }
-
- for (var i = 0; i < paramValues.length; i++) {
- paramValues[i] = JSON.stringify(paramValues[i]);
- }
-
- if (paramValues.length > 0) {
- body.ParamValues = paramValues;
- }
- }
-
- const message = JSON.stringify(body);
-
- var requestUrl = `${window.location.origin}/__hwvInvokeDotNet?data=${encodeURIComponent(message)}`;
-
- const rawResponse = await fetch(requestUrl, {
- method: 'GET',
- headers: {
- 'Accept': 'application/json'
- }
- });
- const response = await rawResponse.json();
-
- if (response) {
- if (response.IsJson) {
- return JSON.parse(response.Result);
- }
-
- return response.Result;
- }
-
- return null;
- },
-
- "__SendMessageInternal": function __SendMessageInternal(type, message) {
-
- const messageToSend = type + '|' + message;
-
- if (window.chrome && window.chrome.webview) {
- // Windows WebView2
- window.chrome.webview.postMessage(messageToSend);
- }
- else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
- // iOS and MacCatalyst WKWebView
- window.webkit.messageHandlers.webwindowinterop.postMessage(messageToSend);
- }
- else {
- // Android WebView
- hybridWebViewHost.sendMessage(messageToSend);
- }
- },
-
- "__InvokeJavaScript": async function __InvokeJavaScript(taskId, methodName, args) {
- try {
- var result = null;
- if (methodName[Symbol.toStringTag] === 'AsyncFunction') {
- result = await methodName(...args);
- } else {
- result = methodName(...args);
- }
- window.HybridWebView.__TriggerAsyncCallback(taskId, result);
- } catch (ex) {
- console.error(ex);
- window.HybridWebView.__TriggerAsyncFailedCallback(taskId, ex);
- }
- },
-
- "__TriggerAsyncFailedCallback": function __TriggerAsyncCallback(taskId, error) {
-
- if (!error) {
- json = {
- Message: "Unknown error",
- StackTrace: Error().stack
- };
- } else if (error instanceof Error) {
- json = {
- Name: error.name,
- Message: error.message,
- StackTrace: error.stack
- };
- } else if (typeof (error) === 'string') {
- json = {
- Message: error,
- StackTrace: Error().stack
- };
- } else {
- json = {
- Message: JSON.stringify(error),
- StackTrace: Error().stack
- };
- }
-
- json = JSON.stringify(json);
-
- window.HybridWebView.__SendMessageInternal('__InvokeJavaScriptFailed', taskId + '|' + json);
- },
-
- "__TriggerAsyncCallback": function __TriggerAsyncCallback(taskId, result) {
- const json = JSON.stringify(result);
- window.HybridWebView.__SendMessageInternal('__InvokeJavaScriptCompleted', taskId + '|' + json);
- }
-}
-
-window.HybridWebView.Init();
diff --git a/src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj b/src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj
index 84cd5c8d3f47..776daee3c3ba 100644
--- a/src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj
+++ b/src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj
@@ -32,6 +32,7 @@
+
diff --git a/src/Controls/tests/DeviceTests/Resources/Raw/HybridTestRoot/scripts/HybridWebView.js b/src/Controls/tests/DeviceTests/Resources/Raw/HybridTestRoot/scripts/HybridWebView.js
deleted file mode 100644
index 52d67172af49..000000000000
--- a/src/Controls/tests/DeviceTests/Resources/Raw/HybridTestRoot/scripts/HybridWebView.js
+++ /dev/null
@@ -1,145 +0,0 @@
-window.HybridWebView = {
- "Init": function Init() {
- function DispatchHybridWebViewMessage(message) {
- const event = new CustomEvent("HybridWebViewMessageReceived", { detail: { message: message } });
- window.dispatchEvent(event);
- }
-
- if (window.chrome && window.chrome.webview) {
- // Windows WebView2
- window.chrome.webview.addEventListener('message', arg => {
- DispatchHybridWebViewMessage(arg.data);
- });
- }
- else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
- // iOS and MacCatalyst WKWebView
- window.external = {
- "receiveMessage": message => {
- DispatchHybridWebViewMessage(message);
- }
- };
- }
- else {
- // Android WebView
- window.addEventListener('message', arg => {
- DispatchHybridWebViewMessage(arg.data);
- });
- }
- },
-
- "SendRawMessage": function SendRawMessage(message) {
- window.HybridWebView.__SendMessageInternal('__RawMessage', message);
- },
-
- "InvokeDotNet": async function InvokeDotNetAsync(methodName, paramValues) {
- const body = {
- MethodName: methodName
- };
-
- if (typeof paramValues !== 'undefined') {
- if (!Array.isArray(paramValues)) {
- paramValues = [paramValues];
- }
-
- for (var i = 0; i < paramValues.length; i++) {
- paramValues[i] = JSON.stringify(paramValues[i]);
- }
-
- if (paramValues.length > 0) {
- body.ParamValues = paramValues;
- }
- }
-
- const message = JSON.stringify(body);
-
- var requestUrl = `${window.location.origin}/__hwvInvokeDotNet?data=${encodeURIComponent(message)}`;
-
- const rawResponse = await fetch(requestUrl, {
- method: 'GET',
- headers: {
- 'Accept': 'application/json'
- }
- });
- const response = await rawResponse.json();
-
- if (response) {
- if (response.IsJson) {
- return JSON.parse(response.Result);
- }
-
- return response.Result;
- }
-
- return null;
- },
-
- "__SendMessageInternal": function __SendMessageInternal(type, message) {
-
- const messageToSend = type + '|' + message;
-
- if (window.chrome && window.chrome.webview) {
- // Windows WebView2
- window.chrome.webview.postMessage(messageToSend);
- }
- else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
- // iOS and MacCatalyst WKWebView
- window.webkit.messageHandlers.webwindowinterop.postMessage(messageToSend);
- }
- else {
- // Android WebView
- hybridWebViewHost.sendMessage(messageToSend);
- }
- },
-
- "__InvokeJavaScript": async function __InvokeJavaScript(taskId, methodName, args) {
- try {
- var result = null;
- if (methodName[Symbol.toStringTag] === 'AsyncFunction') {
- result = await methodName(...args);
- } else {
- result = methodName(...args);
- }
- window.HybridWebView.__TriggerAsyncCallback(taskId, result);
- } catch (ex) {
- console.error(ex);
- window.HybridWebView.__TriggerAsyncFailedCallback(taskId, ex);
- }
- },
-
- "__TriggerAsyncFailedCallback": function __TriggerAsyncCallback(taskId, error) {
-
- if (!error) {
- json = {
- Message: "Unknown error",
- StackTrace: Error().stack
- };
- } else if (error instanceof Error) {
- json = {
- Name: error.name,
- Message: error.message,
- StackTrace: error.stack
- };
- } else if (typeof (error) === 'string') {
- json = {
- Message: error,
- StackTrace: Error().stack
- };
- } else {
- json = {
- Message: JSON.stringify(error),
- StackTrace: Error().stack
- };
- }
-
- json = JSON.stringify(json);
-
- window.HybridWebView.__SendMessageInternal('__InvokeJavaScriptFailed', taskId + '|' + json);
- },
-
- "__TriggerAsyncCallback": function __TriggerAsyncCallback(taskId, result) {
- const json = JSON.stringify(result);
- window.HybridWebView.__SendMessageInternal('__InvokeJavaScriptCompleted', taskId + '|' + json);
- }
-}
-
-window.HybridWebView.Init();
diff --git a/src/Core/src/Core.csproj b/src/Core/src/Core.csproj
index 964514584c44..71304968edb8 100644
--- a/src/Core/src/Core.csproj
+++ b/src/Core/src/Core.csproj
@@ -69,6 +69,24 @@
+
+
+ ES2020
+ false
+ true
+ true
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
<_CopyItems Include="nuget\buildTransitive\**" SubFolder="" Exclude="nuget\**\*.in.*;nuget\**\net-*\*" />
diff --git a/src/Core/src/Handlers/HybridWebView/HybridWebView.js b/src/Core/src/Handlers/HybridWebView/HybridWebView.js
new file mode 100644
index 000000000000..4c6a63f0274d
--- /dev/null
+++ b/src/Core/src/Handlers/HybridWebView/HybridWebView.js
@@ -0,0 +1,189 @@
+/*
+ * This file contains the JavaScript code that the HybridWebView control uses to
+ * communicate between the web view and the .NET host application.
+ *
+ * The JavaScript file is generated from TypeScript and should not be modified
+ * directly. To make changes, modify the TypeScript file and then recompile it.
+ */
+(() => {
+ /*
+ * Initialize the HybridWebView messaging system.
+ * This method is called once when the page is loaded.
+ */
+ function initHybridWebView() {
+ function dispatchHybridWebViewMessage(message) {
+ const event = new CustomEvent('HybridWebViewMessageReceived', { detail: { message: message } });
+ window.dispatchEvent(event);
+ }
+ if (window.chrome?.webview?.addEventListener) {
+ // Windows WebView2
+ window.chrome.webview.addEventListener('message', (arg) => {
+ dispatchHybridWebViewMessage(arg.data);
+ });
+ }
+ else if (window.webkit?.messageHandlers?.webwindowinterop) {
+ // iOS and MacCatalyst WKWebView
+ // @ts-ignore - We are extending the global object here
+ window.external = {
+ receiveMessage: (message) => {
+ dispatchHybridWebViewMessage(message);
+ },
+ };
+ }
+ else {
+ // Android WebView
+ window.addEventListener('message', (arg) => {
+ dispatchHybridWebViewMessage(arg.data);
+ });
+ }
+ }
+ /*
+ * Send a message to the .NET host application.
+ * The message is sent as a string with the following format: `|`.
+ */
+ function sendMessageToDotNet(type, message) {
+ const messageToSend = type + '|' + message;
+ if (window.chrome && window.chrome.webview) {
+ // Windows WebView2
+ window.chrome.webview.postMessage(messageToSend);
+ }
+ else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
+ // iOS and MacCatalyst WKWebView
+ window.webkit.messageHandlers.webwindowinterop.postMessage(messageToSend);
+ }
+ else if (window.hybridWebViewHost) {
+ // Android WebView
+ window.hybridWebViewHost.sendMessage(messageToSend);
+ }
+ else {
+ console.error('Unable to send messages to .NET because the host environment for the HybridWebView was unknown.');
+ }
+ }
+ /*
+ * Send a message to the .NET host application indicating that a JavaScript method invocation failed.
+ * The error message is sent as a string with the following format: `|`.
+ */
+ function invokeJavaScriptFailedInDotNet(taskId, error) {
+ let errorObj;
+ if (!error) {
+ errorObj = {
+ Message: 'Unknown error',
+ StackTrace: Error().stack
+ };
+ }
+ else if (error instanceof Error) {
+ errorObj = {
+ Name: error.name,
+ Message: error.message,
+ StackTrace: error.stack
+ };
+ }
+ else if (typeof error === 'string') {
+ errorObj = {
+ Message: error,
+ StackTrace: Error().stack
+ };
+ }
+ else {
+ errorObj = {
+ Message: JSON.stringify(error),
+ StackTrace: Error().stack
+ };
+ }
+ const json = JSON.stringify(errorObj);
+ sendMessageToDotNet('__InvokeJavaScriptFailed', taskId + '|' + json);
+ }
+ /*
+ * Send a message to the .NET host application indicating that a JavaScript method invocation completed.
+ * The result is sent as a string with the following format: `|`.
+ */
+ function invokeJavaScriptCallbackInDotNet(taskId, result) {
+ const json = JSON.stringify(result);
+ sendMessageToDotNet('__InvokeJavaScriptCompleted', taskId + '|' + json);
+ }
+ const HybridWebView = {
+ /*
+ * Send a raw message to the .NET host application.
+ * The message is sent directly and not processed or serialized.
+ *
+ * @param message The message to send to the .NET host application.
+ */
+ SendRawMessage: function (message) {
+ sendMessageToDotNet('__RawMessage', message);
+ },
+ /*
+ * Invoke a .NET method on the InvokeJavaScriptTarget instance.
+ * The method name and parameters are serialized and sent to the .NET host application.
+ *
+ * @param methodName The name of the .NET method to invoke.
+ * @param paramValues The parameters to pass to the .NET method. If the method takes no parameters, this can be omitted.
+ *
+ * @returns A promise that resolves with the result of the .NET method invocation.
+ */
+ InvokeDotNet: async function (methodName, paramValues) {
+ const body = {
+ MethodName: methodName
+ };
+ // if parameters were provided, serialize them first
+ if (paramValues !== undefined) {
+ if (!Array.isArray(paramValues)) {
+ paramValues = [paramValues];
+ }
+ for (let i = 0; i < paramValues.length; i++) {
+ paramValues[i] = JSON.stringify(paramValues[i]);
+ }
+ if (paramValues.length > 0) {
+ body.ParamValues = paramValues;
+ }
+ }
+ const message = JSON.stringify(body);
+ const requestUrl = `${window.location.origin}/__hwvInvokeDotNet?data=${encodeURIComponent(message)}`;
+ const rawResponse = await fetch(requestUrl, {
+ method: 'GET',
+ headers: {
+ 'Accept': 'application/json'
+ }
+ });
+ const response = await rawResponse.json();
+ if (!response) {
+ return null;
+ }
+ if (response.IsJson) {
+ return JSON.parse(response.Result);
+ }
+ return response.Result;
+ },
+ /*
+ * Invoke a JavaScript method from the .NET host application.
+ * This method is called from the HybridWebViewHandler and is not intended to be used by user applications.
+ *
+ * @param taskId The task ID that was provided by the .NET host application.
+ * @param methodName The JavaScript method to invoke in the global scope.
+ * @param args The arguments to pass to the JavaScript method.
+ *
+ * @returns A promise.
+ */
+ __InvokeJavaScript: async function (taskId, methodName, args) {
+ try {
+ let result = null;
+ // @ts-ignore - We are checking the type of the function here
+ if (methodName[Symbol.toStringTag] === 'AsyncFunction') {
+ result = await methodName(...args);
+ }
+ else {
+ result = methodName(...args);
+ }
+ invokeJavaScriptCallbackInDotNet(taskId, result);
+ }
+ catch (ex) {
+ console.error(ex);
+ invokeJavaScriptFailedInDotNet(taskId, ex);
+ }
+ }
+ };
+ // Make the following APIs available in global scope for invocation from JS
+ // @ts-ignore - We are extending the global object here
+ window['HybridWebView'] = HybridWebView;
+ // Initialize the HybridWebView
+ initHybridWebView();
+})();
diff --git a/src/Core/src/Handlers/HybridWebView/HybridWebView.ts b/src/Core/src/Handlers/HybridWebView/HybridWebView.ts
new file mode 100644
index 000000000000..2657dec19b3d
--- /dev/null
+++ b/src/Core/src/Handlers/HybridWebView/HybridWebView.ts
@@ -0,0 +1,252 @@
+/*
+ * This file contains the JavaScript code that the HybridWebView control uses to
+ * communicate between the web view and the .NET host application.
+ *
+ * The JavaScript file is generated from TypeScript and should not be modified
+ * directly. To make changes, modify the TypeScript file and then recompile it.
+ */
+
+/*
+ * Extend the global objects to include the interfaces that are used by the
+ * HybridWebView and some operating systems and/or browser hosts.
+ */
+interface External {
+ receiveMessage: (message: any) => void;
+}
+interface Window {
+ chrome?: {
+ webview?: {
+ addEventListener: (event: string, handler: (arg: any) => void) => void;
+ postMessage: (message: any) => void;
+ };
+ };
+ webkit?: {
+ messageHandlers?: {
+ webwindowinterop?: {
+ postMessage: (message: any) => void;
+ };
+ };
+ };
+
+ // Declare the global object that we have added on Android.
+ hybridWebViewHost?: {
+ sendMessage: (message: string) => void;
+ };
+}
+
+/*
+ * The following interfaces define the shape of the messages that are sent between
+ * the web view and the .NET host application.
+ */
+interface JSInvokeMethodData {
+ MethodName: string;
+ ParamValues?: string[];
+}
+interface JSInvokeError {
+ Name?: string;
+ Message: string;
+ StackTrace?: string;
+}
+interface DotNetInvokeResult {
+ IsJson: boolean;
+ Result: any;
+}
+
+(() => {
+
+ /*
+ * Initialize the HybridWebView messaging system.
+ * This method is called once when the page is loaded.
+ */
+ function initHybridWebView() {
+ function dispatchHybridWebViewMessage(message: any) {
+ const event = new CustomEvent('HybridWebViewMessageReceived', { detail: { message: message } });
+ window.dispatchEvent(event);
+ }
+
+ if (window.chrome?.webview?.addEventListener) {
+ // Windows WebView2
+ window.chrome.webview.addEventListener('message', (arg: any) => {
+ dispatchHybridWebViewMessage(arg.data);
+ });
+ } else if (window.webkit?.messageHandlers?.webwindowinterop) {
+ // iOS and MacCatalyst WKWebView
+ // @ts-ignore - We are extending the global object here
+ window.external = {
+ receiveMessage: (message: any) => {
+ dispatchHybridWebViewMessage(message);
+ },
+ };
+ } else {
+ // Android WebView
+ window.addEventListener('message', (arg: any) => {
+ dispatchHybridWebViewMessage(arg.data);
+ });
+ }
+ }
+
+ /*
+ * Send a message to the .NET host application.
+ * The message is sent as a string with the following format: `|`.
+ */
+ function sendMessageToDotNet(type: string, message: string) {
+ const messageToSend = type + '|' + message;
+
+ if (window.chrome && window.chrome.webview) {
+ // Windows WebView2
+ window.chrome.webview.postMessage(messageToSend);
+ } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.webwindowinterop) {
+ // iOS and MacCatalyst WKWebView
+ window.webkit.messageHandlers.webwindowinterop.postMessage(messageToSend);
+ } else if (window.hybridWebViewHost) {
+ // Android WebView
+ window.hybridWebViewHost.sendMessage(messageToSend);
+ } else {
+ console.error('Unable to send messages to .NET because the host environment for the HybridWebView was unknown.');
+ }
+ }
+
+ /*
+ * Send a message to the .NET host application indicating that a JavaScript method invocation failed.
+ * The error message is sent as a string with the following format: `|`.
+ */
+ function invokeJavaScriptFailedInDotNet(taskId: string, error: any) {
+ let errorObj: JSInvokeError;
+
+ if (!error) {
+ errorObj = {
+ Message: 'Unknown error',
+ StackTrace: Error().stack
+ };
+ } else if (error instanceof Error) {
+ errorObj = {
+ Name: error.name,
+ Message: error.message,
+ StackTrace: error.stack
+ };
+ } else if (typeof error === 'string') {
+ errorObj = {
+ Message: error,
+ StackTrace: Error().stack
+ };
+ } else {
+ errorObj = {
+ Message: JSON.stringify(error),
+ StackTrace: Error().stack
+ };
+ }
+
+ const json = JSON.stringify(errorObj);
+
+ sendMessageToDotNet('__InvokeJavaScriptFailed', taskId + '|' + json);
+ }
+
+ /*
+ * Send a message to the .NET host application indicating that a JavaScript method invocation completed.
+ * The result is sent as a string with the following format: `|`.
+ */
+ function invokeJavaScriptCallbackInDotNet(taskId: string, result?: any) {
+ const json = JSON.stringify(result);
+
+ sendMessageToDotNet('__InvokeJavaScriptCompleted', taskId + '|' + json);
+ }
+
+ const HybridWebView = {
+
+ /*
+ * Send a raw message to the .NET host application.
+ * The message is sent directly and not processed or serialized.
+ *
+ * @param message The message to send to the .NET host application.
+ */
+ SendRawMessage: function (message: string) {
+ sendMessageToDotNet('__RawMessage', message);
+ },
+
+ /*
+ * Invoke a .NET method on the InvokeJavaScriptTarget instance.
+ * The method name and parameters are serialized and sent to the .NET host application.
+ *
+ * @param methodName The name of the .NET method to invoke.
+ * @param paramValues The parameters to pass to the .NET method. If the method takes no parameters, this can be omitted.
+ *
+ * @returns A promise that resolves with the result of the .NET method invocation.
+ */
+ InvokeDotNet: async function (methodName: string, paramValues?: any) {
+ const body: JSInvokeMethodData = {
+ MethodName: methodName
+ };
+
+ // if parameters were provided, serialize them first
+ if (paramValues !== undefined) {
+ if (!Array.isArray(paramValues)) {
+ paramValues = [paramValues];
+ }
+
+ for (let i = 0; i < paramValues.length; i++) {
+ paramValues[i] = JSON.stringify(paramValues[i]);
+ }
+
+ if (paramValues.length > 0) {
+ body.ParamValues = paramValues;
+ }
+ }
+
+ const message = JSON.stringify(body);
+
+ const requestUrl = `${window.location.origin}/__hwvInvokeDotNet?data=${encodeURIComponent(message)}`;
+
+ const rawResponse = await fetch(requestUrl, {
+ method: 'GET',
+ headers: {
+ 'Accept': 'application/json'
+ }
+ });
+ const response: DotNetInvokeResult = await rawResponse.json();
+
+ if (!response) {
+ return null;
+ }
+
+ if (response.IsJson) {
+ return JSON.parse(response.Result);
+ }
+
+ return response.Result;
+ },
+
+ /*
+ * Invoke a JavaScript method from the .NET host application.
+ * This method is called from the HybridWebViewHandler and is not intended to be used by user applications.
+ *
+ * @param taskId The task ID that was provided by the .NET host application.
+ * @param methodName The JavaScript method to invoke in the global scope.
+ * @param args The arguments to pass to the JavaScript method.
+ *
+ * @returns A promise.
+ */
+ __InvokeJavaScript: async function (taskId: string, methodName: Function, args: any[]) {
+ try {
+ let result: any = null;
+ // @ts-ignore - We are checking the type of the function here
+ if (methodName[Symbol.toStringTag] === 'AsyncFunction') {
+ result = await methodName(...args);
+ } else {
+ result = methodName(...args);
+ }
+ invokeJavaScriptCallbackInDotNet(taskId, result);
+ } catch (ex) {
+ console.error(ex);
+ invokeJavaScriptFailedInDotNet(taskId, ex);
+ }
+ }
+ };
+
+ // Make the following APIs available in global scope for invocation from JS
+ // @ts-ignore - We are extending the global object here
+ window['HybridWebView'] = HybridWebView;
+
+ // Initialize the HybridWebView
+ initHybridWebView();
+
+})();