<commit_before>﻿using ChakraCore.NET.API;
using ChakraCore.NET.Promise;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace ChakraCore.NET
{
    public static class PromiseServiceInjector
    {

        public static void InjectTaskService(this IServiceNode target)
        {
            if (target.CanGetService<PromiseCallbackPairService>())
            {
                return;
            }
            PromiseCallbackPairService service = new PromiseCallbackPairService();
            target.PushService(service);
        }

        public static void RegisterTask(this IJSValueConverterService target)
        {
            if (target.CanConvert<Task>())
            {
                return;
            }
            //register internal call back types
            target.RegisterMethodConverter<string>();
            target.RegisterFunctionConverter<JSValue>();
            target.RegisterMethodConverter<Action, Action<string>>();


            target.RegisterConverter<Task>(
                (node, value) =>
                {
                    //convert resolve, reject
                    Action<Action, Action<string>> promiseBody = async (resolve, reject) =>
                    {
                        try
                        {
                            await value;
                            resolve();
                        }
                        catch (PromiseRejectedException ex)
                        {
                            reject(ex.ToString());
                        }
                        catch (Exception)
                        {
                            throw;
                        }

                    };
                    var jsValueService = node.GetService<IJSValueService>();
                    var globalObject = jsValueService.JSGlobalObject;
                    var jsGlobalObject = new JSValue(node, globalObject);
                    return jsGlobalObject.CallFunction<Action<Action, Action<string>>, JavaScriptValue>("Promise", promiseBody, true);
                },
                (node, value) =>
                {
                    //from a promise 
                    return Task.Factory.FromAsync(

                        (callback, state) =>
                        {
                            return BeginMethod(value, node, callback, state);
                        }
                        , EndMethod, null
                        );


                }, false
                );
        }

        public static void RegisterTask<TResult>(this IJSValueConverterService target)
        {
            if (target.CanConvert<Task<TResult>>())
            {
                return;
            }
            //register internal call back types
            target.RegisterFunctionConverter<TResult>();
            target.RegisterMethodConverter<TResult>();
            target.RegisterMethodConverter<string>();
            target.RegisterFunctionConverter<JSValue>();
            target.RegisterMethodConverter<Action<TResult>, Action<string>>();


            target.RegisterConverter<Task<TResult>>(
                (node, value) =>
                {
                    //convert resolve, reject
                    Action<Action<TResult>, Action<string>> promiseBody = async (resolve, reject) =>
                       {
                           try
                           {
                               var result = await value;
                               resolve(result);
                           }
                           catch (PromiseRejectedException ex)
                           {
                               reject(ex.ToString());
                           }
                           catch (Exception)
                           {
                               throw;
                           }
                           
                       };
                    var jsValueService = node.GetService<IJSValueService>();
                    var globalObject = jsValueService.JSGlobalObject;
                    var jsGlobalObject = new JSValue(node, globalObject);
                    return jsGlobalObject.CallFunction<Action<Action<TResult>, Action<string>>, JavaScriptValue>("Promise", promiseBody, true);
                },
                (node, value) =>
                {
                    //from a promise 
                    return Task.Factory.FromAsync(

                        (callback, state) =>
                        {
                            return BeginMethod<TResult>(value, node, callback, state);
                        }
                        , EndMethod<TResult>, null
                        );


                }, false
                );
        }

        private static IAsyncResult BeginMethod(JavaScriptValue func, IServiceNode node, AsyncCallback callback, object state)
        {
            var conveter = node.GetService<IJSValueConverterService>();
            var result = new AsyncResult();
            Action fullfilledCallback = () =>
            {
                callback(result);
            };
            Action<JavaScriptValue> rejectedCallback = (s) =>
            {
                result.SetError(s);
                callback(result);
            };

            Func<JSValue> promiseCall = conveter.FromJSValue<Func<JSValue>>(func);// the target function which returns a promise object
            JSValue promiseObject = promiseCall();//call the function,get the Promise object
            var service = promiseObject.ServiceNode.GetService<PromiseCallbackPairService>();//get the delegate interceptor
            service.Begin();//enable the interceptor
            promiseObject.CallMethod("then", fullfilledCallback, rejectedCallback);
            System.Diagnostics.Debug.WriteLine("[Then] called");
            service.End();//disable the interceptor
            return result;
        }

        private static IAsyncResult BeginMethod<T>(JavaScriptValue func, IServiceNode node, AsyncCallback callback, object state)
        {
            var conveter = node.GetService<IJSValueConverterService>();
            var result = new AsyncResult<T>();
            Action<T> fullfilledCallback = (x) =>
            {
                result.SetResult(x);
                callback(result);
            };
            Action<JavaScriptValue> rejectedCallback = (s) =>
            {
                result.SetError(s);
                callback(result);
            };

            Func<JSValue> promiseCall = conveter.FromJSValue<Func<JSValue>>(func);// the target function which returns a promise object
            JSValue promiseObject = promiseCall();//call the function,get the Promise object
            var service=promiseObject.ServiceNode.GetService<PromiseCallbackPairService>();//get the delegate interceptor
            service.Begin();//enable the interceptor
            promiseObject.CallMethod("then", fullfilledCallback, rejectedCallback);
            System.Diagnostics.Debug.WriteLine("[Then] called");
            service.End();//disable the interceptor
            return result;
        }

        private static T EndMethod<T>(IAsyncResult result)
        {
            var asyncResult = result as AsyncResult<T> ?? throw new ArgumentException("Result is of wrong type.");
            if (asyncResult.Error.ValueType == JavaScriptValueType.Error) throw new PromiseRejectedException(asyncResult.Error);
            return asyncResult.Result;
        }

        private static void EndMethod(IAsyncResult result)
        {
            var asyncResult = result as AsyncResult ?? throw new ArgumentException("Result is of wrong type.");
            if (asyncResult.Error.ValueType == JavaScriptValueType.Error) throw new PromiseRejectedException(asyncResult.Error);
        }
        
    }
}<commit_msg>PromiseServiceInjector fixed.<commit_after>﻿using ChakraCore.NET.API;
using ChakraCore.NET.Promise;
using System;
using System.Threading.Tasks;

namespace ChakraCore.NET
{
    public static class PromiseServiceInjector
    {

        public static void InjectTaskService(this IServiceNode target)
        {
            if (target.CanGetService<PromiseCallbackPairService>())
            {
                return;
            }
            PromiseCallbackPairService service = new PromiseCallbackPairService();
            target.PushService(service);
        }

        public static void RegisterTask(this IJSValueConverterService target)
        {
            if (target.CanConvert<Task>())
            {
                return;
            }
            //register internal call back types
            target.RegisterMethodConverter<string>();
            target.RegisterFunctionConverter<JSValue>();
            target.RegisterMethodConverter<Action, Action<JavaScriptValue>>();


            target.RegisterConverter<Task>(
                (node, value) =>
                {
                    //convert resolve, reject
                    Action<Action, Action<JavaScriptValue>> promiseBody = async (resolve, reject) =>
                    {
                        try
                        {
                            await value;
                            resolve();
                        }
                        catch (PromiseRejectedException ex)
                        {
                            reject(ex.Error);
                        }
                        catch (Exception)
                        {
                            throw;
                        }

                    };
                    var jsValueService = node.GetService<IJSValueService>();
                    var globalObject = jsValueService.JSGlobalObject;
                    var jsGlobalObject = new JSValue(node, globalObject);
                    return jsGlobalObject.CallFunction<Action<Action, Action<JavaScriptValue>>, JavaScriptValue>("Promise", promiseBody, true);
                },
                (node, value) =>
                {
                    //from a promise 
                    return Task.Factory.FromAsync(

                        (callback, state) =>
                        {
                            return BeginMethod(value, node, callback, state);
                        }
                        , EndMethod, null
                        );


                }, false
                );
        }

        public static void RegisterTask<TResult>(this IJSValueConverterService target)
        {
            if (target.CanConvert<Task<TResult>>())
            {
                return;
            }
            //register internal call back types
            target.RegisterFunctionConverter<TResult>();
            target.RegisterMethodConverter<TResult>();
            target.RegisterMethodConverter<string>();
            target.RegisterFunctionConverter<JSValue>();
            target.RegisterMethodConverter<Action<TResult>, Action<JavaScriptValue>>();


            target.RegisterConverter<Task<TResult>>(
                (node, value) =>
                {
                    //convert resolve, reject
                    Action<Action<TResult>, Action<JavaScriptValue>> promiseBody = async (resolve, reject) =>
                       {
                           try
                           {
                               var result = await value;
                               resolve(result);
                           }
                           catch (PromiseRejectedException ex)
                           {
                               reject(ex.Error);
                           }
                           catch (Exception)
                           {
                               throw;
                           }
                           
                       };
                    var jsValueService = node.GetService<IJSValueService>();
                    var globalObject = jsValueService.JSGlobalObject;
                    var jsGlobalObject = new JSValue(node, globalObject);
                    return jsGlobalObject.CallFunction<Action<Action<TResult>, Action<JavaScriptValue>>, JavaScriptValue>("Promise", promiseBody, true);
                },
                (node, value) =>
                {
                    //from a promise 
                    return Task.Factory.FromAsync(

                        (callback, state) =>
                        {
                            return BeginMethod<TResult>(value, node, callback, state);
                        }
                        , EndMethod<TResult>, null
                        );


                }, false
                );
        }

        private static IAsyncResult BeginMethod(JavaScriptValue func, IServiceNode node, AsyncCallback callback, object state)
        {
            var conveter = node.GetService<IJSValueConverterService>();
            var result = new AsyncResult();
            Action fullfilledCallback = () =>
            {
                callback(result);
            };
            Action<JavaScriptValue> rejectedCallback = (s) =>
            {
                result.SetError(s);
                callback(result);
            };

            Func<JSValue> promiseCall = conveter.FromJSValue<Func<JSValue>>(func);// the target function which returns a promise object
            JSValue promiseObject = promiseCall();//call the function,get the Promise object
            var service = promiseObject.ServiceNode.GetService<PromiseCallbackPairService>();//get the delegate interceptor
            service.Begin();//enable the interceptor
            promiseObject.CallMethod("then", fullfilledCallback, rejectedCallback);
            System.Diagnostics.Debug.WriteLine("[Then] called");
            service.End();//disable the interceptor
            return result;
        }

        private static IAsyncResult BeginMethod<T>(JavaScriptValue func, IServiceNode node, AsyncCallback callback, object state)
        {
            var conveter = node.GetService<IJSValueConverterService>();
            var result = new AsyncResult<T>();
            Action<T> fullfilledCallback = (x) =>
            {
                result.SetResult(x);
                callback(result);
            };
            Action<JavaScriptValue> rejectedCallback = (s) =>
            {
                result.SetError(s);
                callback(result);
            };

            Func<JSValue> promiseCall = conveter.FromJSValue<Func<JSValue>>(func);// the target function which returns a promise object
            JSValue promiseObject = promiseCall();//call the function,get the Promise object
            var service=promiseObject.ServiceNode.GetService<PromiseCallbackPairService>();//get the delegate interceptor
            service.Begin();//enable the interceptor
            promiseObject.CallMethod("then", fullfilledCallback, rejectedCallback);
            System.Diagnostics.Debug.WriteLine("[Then] called");
            service.End();//disable the interceptor
            return result;
        }

        private static T EndMethod<T>(IAsyncResult result)
        {
            var asyncResult = result as AsyncResult<T> ?? throw new ArgumentException("Result is of wrong type.");
            if (asyncResult.Error.IsValid) throw new PromiseRejectedException(asyncResult.Error);
            return asyncResult.Result;
        }

        private static void EndMethod(IAsyncResult result)
        {
            var asyncResult = result as AsyncResult ?? throw new ArgumentException("Result is of wrong type.");
            if (asyncResult.Error.ValueType == JavaScriptValueType.Error) throw new PromiseRejectedException(asyncResult.Error);
        }
        
    }
}
{'fraction_non_alphanumeric': 0.08229537366548043, 'fraction_numerical': 0.0, 'mean_word_length': 1.3775494787732285, 'pattern_counts': {'":': 0, '<': 107, '<?xml version=': 0, '>': 131, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6268227', 'n_tokens_mistral': 3397, 'n_tokens_neox': 3216, 'n_words': 722}