Skip to content

Instantly share code, notes, and snippets.

@Dubiy
Created July 4, 2023 06:33
Show Gist options
  • Save Dubiy/ed4ada7bae6f8557c1d7ce9ace4dd1bf to your computer and use it in GitHub Desktop.
Save Dubiy/ed4ada7bae6f8557c1d7ce9ace4dd1bf to your computer and use it in GitHub Desktop.
using Jint;
using UnityEngine;
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Timers;
public class RunJs : MonoBehaviour
{
private static Engine engine;
private static Dictionary<int, Timer> timers;
private static int timerIdCounter = 0;
void Start()
{
engine = new Engine();
timers = new Dictionary<int, Timer>(); // Initialize the timers dictionary
engine.SetValue("console",typeof(Debug));
engine.Execute("window = {};");
engine.Execute("global = {};");
engine.SetValue("setTimeout", new Action<Action, double>(SetTimeout));
// engine.SetValue("fetch", new Func<RequestObj, FetchResponse>(Fetch));
engine.SetValue("XMLHttpRequest", typeof(XMLHTTPRequest));
// var source = new StreamReader(Application.dataPath + "/Resources/" + "JSWrapper.bundle.js");
// string script = source.ReadToEnd();
// source.Close();
// engine.Execute(script);
// engine.Evaluate("window.bladeSdk.init('...apiKey...', 'dappcode', 'initBladeSdkJS1')").ToObject();
engine.Execute(@"
(() => {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.log(JSON.stringify(xhr));
}
// setTimeout(function() {
// resolve(`resolve from timeout FAILS ${JSON.stringify(xhr)}`);
// }, 0);
};
// setTimeout(function() {
// resolve(`resolve from timeout OK`);
// }, 0);
xhr.open('GET', 'https://mainnet-public.mirrornode.hedera.com/api/v1/accounts/0.0.3333', true);
xhr.onload = function() {
console.log('on Load invoked');
setTimeout(function() {
resolve(`resolve from timeout FAILS here too`);
}, 0);
}
xhr.send();
})
})()
.then(res => {
console.log(`PROMISE resolve: ${res}`)
})
.catch(res => {
console.log(`PROMISE reject: ${res}`)
})
");
static FetchResponse Fetch(RequestObj request)
{
var url = request.url;
var fetchResponse = new FetchResponse();
Task.Run(async () =>
{
try
{
using (var httpClient = new HttpClient())
{
var response = await httpClient.GetAsync(url);
var content = await response.Content.ReadAsStringAsync();
var result = new
{
ok = response.IsSuccessStatusCode,
status = (int)response.StatusCode,
statusText = response.StatusCode.ToString(),
text = new Func<string>(() => content),
json = new Func<string>(() => content)
};
fetchResponse.Resolve(result);
}
}
catch (Exception e)
{
var result = new
{
ok = false,
status = 0,
statusText = e.Message,
text = new Func<string>(() => string.Empty),
json = new Func<string>(() => string.Empty)
};
fetchResponse.Reject(result);
}
});
return fetchResponse;
}
}
static void SetTimeout(Action callback, double delay)
{
Timer timer = new Timer(delay+1);
timer.Elapsed += (sender, args) =>
{
callback.Invoke();
timer.Stop();
timer.Dispose();
};
int timerId = timerIdCounter++;
timers[timerId] = timer;
timer.Start();
}
}
public class RequestObj
{
public string url { get; set; }
public string method { get; set; } = "get";
public override string ToString()
{
return $"url: {url}, method: {method}";
}
}
class FetchResponse
{
private Action<object> resolveCallback;
private Action<object> rejectCallback;
public void Resolve(object result)
{
resolveCallback?.Invoke(result);
}
public void Reject(object error)
{
rejectCallback?.Invoke(error);
}
// set callbacks.
// TODO: chain callbacks
public FetchResponse Then(Action<object> onResolved)
{
resolveCallback = onResolved;
return this;
}
public FetchResponse Catch(Action<object> onRejected)
{
rejectCallback = onRejected;
return this;
}
}
public class XMLHTTPRequest
{
private HttpClient client;
private HttpRequestMessage request;
private HttpResponseMessage response;
private Action onReadyStateChange;
private Action onLoad;
private Action onError;
private Action onTimeout;
private Action onAbort;
private bool isPolling;
public XMLHTTPRequest()
{
client = new HttpClient();
request = new HttpRequestMessage();
isPolling = false;
}
public void open(string method, string url, bool async = true)
{
request.Method = new HttpMethod(method);
request.RequestUri = new Uri(url);
}
public void send(string bodyInit = "")
{
response = client.SendAsync(request).GetAwaiter().GetResult();
StartPolling();
}
private async void StartPolling()
{
int delay = 100;
int timeout = 30000;
isPolling = true;
while (isPolling)
{
await Task.Delay(delay); // Adjust the polling interval as needed
timeout -= delay;
if ((int)(response?.StatusCode ?? 0) > 0) {
Debug.Log("response code: " + response?.StatusCode);
isPolling = false;
Debug.Log("onLoad?: " + onLoad);
onReadyStateChange?.Invoke();
onLoad?.Invoke();
}
// TODO on error
if (timeout <= 0) {
onTimeout?.Invoke();
onAbort?.Invoke();
}
}
}
public void abort()
{
isPolling = false;
request.Dispose();
onAbort?.Invoke();
}
public string getAllResponseHeaders() {
return "";
}
public string responseText
{
get
{
return response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
}
}
public int status
{
get
{
return (int)(response?.StatusCode ?? 0);
}
}
public int readyState
{
get
{
return isPolling ? 3 : 4;
}
}
public Action onreadystatechange
{
get
{
return onReadyStateChange;
}
set
{
Debug.Log("onreadystatechange set");
onReadyStateChange = value;
}
}
public Action onload
{
get
{
return onLoad;
}
set
{
Debug.Log("onload set");
onLoad = value;
}
}
public Action onerror
{
get
{
return onError;
}
set
{
Debug.Log("onerror set");
onError = value;
}
}
public Action ontimeout
{
get
{
return onTimeout;
}
set
{
Debug.Log("ontimeout set");
onTimeout = value;
}
}
public Action onabort
{
get
{
return onAbort;
}
set
{
Debug.Log("onabort set");
onAbort = value;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment