Пример #1
0
        // X:\jsc.svn\examples\javascript\Test\TestServiceWorker\TestServiceWorker\Application.cs

        // jsc wont yet allow to return Task from native apis?
        // need manual extensions for now?
        public static Task<ServiceWorkerRegistration> register(this ServiceWorkerContainer serviceworker)
        {
            var x = serviceworker.register(
                InternalInlineWorker.GetScriptApplicationSourceForInlineWorker(),
                null
            );


            return x.AsTask();
        }
Пример #2
0
        // X:\jsc.svn\examples\javascript\async\test\TestSwitchToServiceContextAsync\TestSwitchToServiceContextAsync\Application.cs

        // called by
        // Task.Run,
        // Task.ctor
        // TaskFactory.StartNew

        public void InternalInitializeInlineWorker(
            //Func<object, TResult> function,
            Delegate function,

            object state,

            CancellationToken c,
            TaskCreationOptions o,
            TaskScheduler s,


            // X:\jsc.svn\examples\javascript\async\AsyncHopToUIFromWorker\AsyncHopToUIFromWorker\Application.cs
            // allow special callbacks
            Action <Worker, MessageEvent> yield = null
            )
        {
            var InternalThreadCounter = InternalInlineWorker.InternalThreadCounter;

            InternalInlineWorker.InternalThreadCounter++;



            Delegate xfunction = function;

            #region WriteLine
            Action <string> UIWriteLine =
                text =>
            {
                if (InternalInlineWorkerTextWriter.WorkerConsoleDisabled)
                {
                    return;
                }

                // () means we are setting the thread up... [] is the thread
                Console.WriteLine("UI(" + InternalThreadCounter + ") " + text);
            };
            #endregion

            //WriteLine("enter InternalInitializeInlineWorker");


            // whatif the delegate is Action?

            // X:\jsc.svn\examples\javascript\Test\TestRedirectWebWorker\TestRedirectWebWorker\Application.cs
            // what happened? also, as interface cannot handle ull yet


            var MethodType = typeof(FuncOfObjectToObject).Name;



            // what if this is a GUI task?

            // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2013/201308/20130828-thread-run

            #region MethodToken


            // X:\jsc.svn\examples\javascript\Test\TestHopToThreadPoolAwaitable\TestHopToThreadPoolAwaitable\Application.cs


            if (xfunction.Target != null)
            {
                if (xfunction.Target != Native.self)
                {
                    // X:\jsc.svn\examples\javascript\Test\TestMemoryStreamPerformance\TestMemoryStreamPerformance\Application.cs
                    // X:\jsc.svn\examples\javascript\async\AsyncNonStaticHandler\AsyncNonStaticHandler\Application.cs

                    var TargetType = xfunction.Target.GetType();

                    //Console.WriteLine("InternalInitializeInlineWorker " + new { Target = function.Target.ToString(), TargetType });

                    // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs
                    Delegate InternalTaskExtensionsScope_function = (xfunction.Target as dynamic).InternalTaskExtensionsScope_function;
                    // X:\jsc.svn\core\ScriptCoreLib.Extensions\ScriptCoreLib.Extensions\Extensions\TaskExtensions.cs

                    if (InternalTaskExtensionsScope_function != null)
                    {
                        //MethodToken = ((__MethodInfo)InternalTaskExtensionsScope_function.Method).InternalMethodToken;

                        xfunction = InternalTaskExtensionsScope_function;
                    }
                }
            }
            #endregion

            var MethodToken = ((__MethodInfo)xfunction.Method).InternalMethodToken;



            #region MethodTargetTypeIndex
            var MethodTargetTypeIndex = default(object);



            // shall we get level2 types accross
            // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2014/201411/20141112
            var MethodTargetObjectDataTypes = default(object[]);

            var MethodTargetObjectData           = default(object[]);
            var MethodTargetObjectDataProgress   = default(__IProgress <object>[]);
            var MethodTargetObjectDataIsProgress = default(bool[]);

            // we need to send in also the this argument of the function, lets find whats the token of the type
            if (xfunction.Target != null)
            {
                // functions bound to self/window are considered to be static
                if (xfunction.Target != Native.self)
                {
                    // X:\jsc.svn\examples\javascript\async\AsyncNonStaticHandler\AsyncNonStaticHandler\Application.cs

                    var TargetType = xfunction.Target.GetType();

                    MethodTargetTypeIndex = __Type.GetTypeIndex("TargetType", TargetType);


                    // lets hope all the fields are transferable!

                    var MethodTargetSerializableMembers = FormatterServices.GetSerializableMembers(TargetType);

                    //foreach (var item in MethodTargetSerializableMembers)
                    //{
                    //    // do we have usage/security information available from the analyzer?
                    //    Console.WriteLine("__Task will share scope, field " + item.Name);
                    //    // for scope sharing first we may see IEvent. that cannot be sent over
                    //    // as it is not a primitive and not under our control either
                    //    // how can we exclude it?
                    //    // we should also know who exactyl can use it in the inner scope
                    //}

                    MethodTargetObjectData = FormatterServices.GetObjectData(xfunction.Target, MethodTargetSerializableMembers);

                    // X:\jsc.svn\examples\javascript\async\test\TestWorkerScopeProgress\TestWorkerScopeProgress\Application.cs
                    MethodTargetObjectDataTypes      = new object[MethodTargetObjectData.Length];
                    MethodTargetObjectDataProgress   = new __IProgress <object> [MethodTargetObjectData.Length];
                    MethodTargetObjectDataIsProgress = new bool[MethodTargetObjectData.Length];

                    for (int i = 0; i < MethodTargetObjectData.Length; i++)
                    {
                        var MemberName  = MethodTargetSerializableMembers[i].Name;
                        var MemberValue = MethodTargetObjectData[i];

                        if (MemberValue != null)
                        {
                            //0:6967ms __Task scope { MemberName = foo, isString = false, isInt32 = false, idx = vgAABBwAgD2RX0Pk4wU2RQ }
                            // 0:5749ms __Task scope { MemberName = foo, isString = false, isInt32 = false, idx = vgAABBwAgD2RX0Pk4wU2RQ, MemberType = <Namespace>. }
                            // 0:3093ms __Task scope { MemberName = row, isString = false, isInt32 = false, idx = type$_2LWH6_a6FzTCDOJSbur6JKQ, MemberType = <Namespace>.xRow }

                            // is it our type/secure or not? or is it primitive?
                            var MemberType = MemberValue.GetType();

                            var IsString = Expando.Of(MemberValue).IsString;
                            //var isString = MemberType == typeof(string);
                            //var isInt32 = MemberType == typeof(int);
                            var IsNumber    = Expando.Of(MemberValue).IsNumber;
                            var IsByteArray = Expando.Of(MemberValue).IsByteArray;

                            // are we to send typeIndex to the other side for member reconstruction?
                            var TypeIndex = __Type.GetTypeIndex(MemberName, MemberType);

                            MethodTargetObjectDataTypes[i] = TypeIndex;

                            //0:4812ms __Task scope { MemberName = scope1, isString = false, isInt32 = false } view-source:40687
                            //0:4814ms __Task scope { MemberName = e, isString = false, isInt32 = false }



                            // null it out as we are not able to clone that object for the other thread
                            if (TypeIndex == null)
                            {
                                if (!IsString)
                                {
                                    if (!IsNumber)
                                    {
                                        if (!IsByteArray)
                                        {
                                            MethodTargetObjectData[i] = null;
                                        }
                                    }
                                }
                            }

                            // we do not know yet how to handle cloning events on level2
                            var IsDelegate = MemberValue is Delegate;
                            if (IsDelegate)
                            {
                                MethodTargetObjectData[i] = null;
                            }



                            #region xSemaphoreSlim
                            // X:\jsc.svn\core\ScriptCoreLib\JavaScript\DOM\Worker.cs

                            // X:\jsc.svn\examples\javascript\async\Test\TestSemaphoreSlim\TestSemaphoreSlim\ApplicationControl.cs
                            var xSemaphoreSlim = MemberValue as __SemaphoreSlim;
                            if (xSemaphoreSlim != null)
                            {
                                // will sending a null over create the object on the other side?
                                MethodTargetObjectData[i] = null;


                                var             MemberName0  = MemberName;
                                Action <string> UIWriteLine0 = text =>
                                {
                                    UIWriteLine("$" + MemberName0 + " " + text);
                                };


                                // we need to entangle the fields in current and the new thread..
                                // if we were to get the signal, how?

                                // 1 or more

                                //var xInternalVirtualWaitAsync = default(TaskCompletionSource<object>);

                                // X:\jsc.svn\examples\javascript\async\test\TestSemaphoreSlimAwaitThenReleaseInWorker\TestSemaphoreSlimAwaitThenReleaseInWorker\Application.cs
                                // is somebody already awaiting?
                                var xInternalVirtualWaitAsyncTask = new TaskCompletionSource <TaskCompletionSource <object> >();
                                var xInternalVirtualWaitAsync     = xSemaphoreSlim.InternalVirtualWaitAsync0;
                                if (xInternalVirtualWaitAsync != null)
                                {
                                    xInternalVirtualWaitAsyncTask.SetResult(xInternalVirtualWaitAsync);
                                }

                                xSemaphoreSlim.InternalVirtualWaitAsync += continuation =>
                                {
                                    UIWriteLine0("enter xSemaphoreSlim.InternalVirtualWaitAsync, ui is now awaiting for signal " + new { xSemaphoreSlim.Name });

                                    // we need a signal from the worker, or the ui
                                    xInternalVirtualWaitAsync = continuation;
                                    xInternalVirtualWaitAsyncTask.SetResult(xInternalVirtualWaitAsync);
                                };



                                var xSemaphoreSlim_InternalIsEntangled = false;

                                // called by?
                                #region yield_xSemaphoreSlim
                                Action <Worker, MessageEvent> yield_xSemaphoreSlim =


                                    // we want in. lets wait for messages from the thread..
                                    //yield += (Worker worker, MessageEvent e) =>
                                    (Worker worker, MessageEvent e) =>
                                {
                                    dynamic data             = e.data;
                                    string  __xSemaphoreSlim = data.xSemaphoreSlim;

                                    if (__xSemaphoreSlim == null)
                                    {
                                        return;
                                    }


                                    if (__xSemaphoreSlim != MemberName0)
                                    {
                                        return;
                                    }

                                    //

                                    // now we have a port to send the release signal?
                                    //WriteLine("xSemaphoreSlim MessageEvent " + new { MemberName0 });

                                    // next will be a release from the worker?

                                    // we made contact!
                                    #region InternalVirtualRelease
                                    if (!xSemaphoreSlim_InternalIsEntangled)
                                    {
                                        UIWriteLine0("yield_xSemaphoreSlim, worker is now listening for release signal");

                                        xSemaphoreSlim_InternalIsEntangled = true;

                                        xSemaphoreSlim.InternalVirtualRelease += delegate
                                        {
                                            // um. we need to post a message to the other side.
                                            // do we have a port channel for it?
                                            // does the other side expect signals?

                                            //WriteLine("xSemaphoreSlim.InternalVirtualRelease " + new { MemberName0 });
                                            UIWriteLine0("xSemaphoreSlim.InternalVirtualRelease, ui is sending signal to worker, resync");

                                            // xSemaphoreSlim_ByteArrayFields
                                            #region xSemaphoreSlim_ByteArrayFields
                                            var xSemaphoreSlim_ByteArrayFields = new List <__Task.xByteArrayField>();


                                            var MethodTargetTypeSerializableMembers_index = 0;

                                            // MethodTargetSerializableMembers
                                            // MethodTargetTypeSerializableMembers

                                            foreach (FieldInfo item in MethodTargetSerializableMembers)
                                            {
                                                // how would we know if the array is a byte array?

                                                // FieldType is not exactly available yet
                                                //Console.WriteLine("worker resync candidate " + new { item.Name, item.FieldType, item.FieldType.IsArray });

                                                var item_value = item.GetValue(xfunction.Target);
                                                if (item_value != null)
                                                {
                                                    var item_value_IsByteArray = Expando.Of(item_value).IsByteArray;

                                                    if (item_value_IsByteArray)
                                                    {
                                                        var value = (byte[])item_value;

                                                        xSemaphoreSlim_ByteArrayFields.Add(
                                                            new __Task.xByteArrayField
                                                        {
                                                            index = MethodTargetTypeSerializableMembers_index,

                                                            // keep name for diagnostics
                                                            Name = item.Name,

                                                            value = value
                                                        }
                                                            );

                                                        UIWriteLine0("ui to worker resync xByteArrayField candidate " + new { item.Name, value.Length });
                                                    }
                                                }


                                                MethodTargetTypeSerializableMembers_index++;
                                            }
                                            #endregion

                                            foreach (var p in e.ports)
                                            {
                                                // release 1
                                                p.postMessage(
                                                    new
                                                {
                                                    // X:\jsc.svn\examples\javascript\async\Test\TestBytesToSemaphore\TestBytesToSemaphore\Application.cs
                                                    xSemaphoreSlim_ByteArrayFields = xSemaphoreSlim_ByteArrayFields.ToArray()
                                                }
                                                    );
                                            }
                                        };

                                        return;
                                    }
                                    #endregion


                                    // now wait for release from worker?

                                    // we never get the message?
                                    //e.ports[0].onmessage += ee =>
                                    //{
                                    //	Console.WriteLine("xSemaphoreSlim port0 onmessage " + new { MemberName0 });
                                    //};



                                    //e.ports[1].onmessage += ee =>
                                    //{
                                    //	Console.WriteLine("xSemaphoreSlim port1 onmessage " + new { MemberName0 });
                                    //};

                                    // workaround?

                                    UIWriteLine0("yield_xSemaphoreSlim, worker sent a release signal to UI, resync " + new { xInternalVirtualWaitAsyncTask.Task.IsCompleted });


                                    #region read xSemaphoreSlim_ByteArrayFields
                                    {
                                        __Task.xByteArrayField[] xSemaphoreSlim_ByteArrayFields = data.xSemaphoreSlim_ByteArrayFields;
                                        // 55779ms ui xSemaphoreSlim MessageEvent, resync, trigger InternalVirtualWaitAsync? {{ MemberName0 = bytes1sema, xInternalVirtualWaitAsync = [object Object], Length = 1 }}

                                        //Console.WriteLine("ui xSemaphoreSlim MessageEvent, resync, trigger InternalVirtualWaitAsync? " + new { MemberName0, xInternalVirtualWaitAsync, xSemaphoreSlim_ByteArrayFields.Length });

                                        // X:\jsc.svn\examples\javascript\async\test\TestBytesToSemaphore\TestBytesToSemaphore\Application.cs
                                        if (xSemaphoreSlim_ByteArrayFields != null)
                                        {
                                            foreach (var item in xSemaphoreSlim_ByteArrayFields)
                                            {
                                                var xFieldInfo = (FieldInfo)MethodTargetSerializableMembers[item.index];

                                                // X:\jsc.svn\examples\javascript\chrome\apps\ChromeThreadedCameraTracker\ChromeThreadedCameraTracker\Application.cs

                                                // can we set the value?
                                                UIWriteLine("ui resync " + new
                                                {
                                                    item.index,
                                                    //item.Name,
                                                    xFieldInfo = xFieldInfo.Name,
                                                    //item.value
                                                });

                                                xFieldInfo.SetValue(
                                                    xfunction.Target,

                                                    // null?
                                                    item.value
                                                    );
                                            }
                                        }
                                    }
                                    #endregion


                                    // what happens if we wnt to signal but nobody is waiting?
                                    // X:\jsc.svn\examples\javascript\async\test\TestBytesToSemaphore\TestBytesToSemaphore\Application.cs
                                    // X:\jsc.svn\examples\javascript\async\test\TestBytesFromSemaphore\TestBytesFromSemaphore\Application.cs



                                    xInternalVirtualWaitAsyncTask.Task.ContinueWith(
                                        __xInternalVirtualWaitAsync =>
                                    {
                                        UIWriteLine0("yield_xSemaphoreSlim, expect a new awaiter now?");

                                        //if (xInternalVirtualWaitAsync == null)
                                        //{
                                        //    UIWriteLine0("cannot signal, xInternalVirtualWaitAsync is null, why? missed by 1?");
                                        //}
                                        //else
                                        //{
                                        //    UIWriteLine0("yield_xSemaphoreSlim, expect a new awaiter now?");
                                        // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/20150706/20150712/rgba_bytes0out_set
                                        xInternalVirtualWaitAsync     = null;
                                        xInternalVirtualWaitAsyncTask = new TaskCompletionSource <TaskCompletionSource <object> >();

                                        __xInternalVirtualWaitAsync.Result.SetResult(null);
                                        //}
                                    }
                                        );
                                };
                                #endregion



                                yield += yield_xSemaphoreSlim;
                            }
                            #endregion


                            // X:\jsc.svn\examples\javascript\async\test\TestWorkerScopeProgress\TestWorkerScopeProgress\Application.cs
                            var IsProgress = MemberValue is __IProgress <object>;
                            if (IsProgress)
                            {
                                MethodTargetObjectDataProgress[i] = (__IProgress <object>)MemberValue;
                                MethodTargetObjectData[i]         = null;

                                // let worker know we want progress reports sent back to us
                                MethodTargetObjectDataIsProgress[i] = true;
                            }

                            // X:\jsc.svn\examples\javascript\async\test\TestScopeWithDelegate\TestScopeWithDelegate\Application.cs
                            // lets make sure no delegates are at level2 either


                            var scope2 = MethodTargetObjectData[i];

                            if (IsString)
                            {
                                // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150428

                                // see path yet?
                                //Console.WriteLine("string: " + new { MemberName, scope2 });
                            }
                            else if (xSemaphoreSlim != null)
                            {
                                // the first entangled method. should we look a the fields?
                                //Console.WriteLine("xSemaphoreSlim: " + new { MemberName });
                            }
                            else
                            {
                                if (scope2 != null)
                                {
                                    // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2014/201411/20141112
                                    // x:\jsc.svn\examples\javascript\test\testhoptothreadpoolawaitable\testhoptothreadpoolawaitable\application.cs


                                    var scope2Type = scope2.GetType();
                                    var scope2TypeSerializableMembers = FormatterServices.GetSerializableMembers(scope2Type);

                                    if (scope2TypeSerializableMembers.Length > 0)
                                    {
                                        // are there any members?
                                        UIWriteLine("will inspect scope2 as " + new { MemberName, scope2TypeSerializableMembers.Length });
                                        var scope2ObjectData = FormatterServices.GetObjectData(scope2, scope2TypeSerializableMembers);

                                        // the hacky way. later we need to refactor this a lot.
                                        for (int ii = 0; ii < scope2ObjectData.Length; ii++)
                                        {
                                            var scope2FieldName = scope2TypeSerializableMembers[ii].Name;

                                            UIWriteLine("scope2: " + MemberName + "." + scope2FieldName);


                                            var scope2value = scope2ObjectData[ii];
                                            if (scope2value != null)
                                            {
                                                var scope2IsDelegate = scope2value is Delegate;
                                                if (scope2IsDelegate)
                                                {
                                                    scope2ObjectData[ii] = null;

                                                    UIWriteLine("scope2 delegate discarded " + new { MemberName, scope2FieldName });
                                                }
                                            }
                                        }

                                        // um. lets remove typeinfo?
                                        // why? to get defaults?
                                        var scope2copy = FormatterServices.GetUninitializedObject(scope2Type);
                                        FormatterServices.PopulateObjectMembers(scope2copy, scope2TypeSerializableMembers, scope2ObjectData);
                                        MethodTargetObjectData[i] = scope2copy;
                                    }
                                }
                            }



                            UIWriteLine(
                                "Task scope " +
                                new
                            {
                                MemberName,
                                IsString,
                                IsNumber,
                                IsDelegate,
                                IsProgress,

                                // will
                                TypeIndex
                            }
                                );
                        }
                    }
                }
            }
            #endregion



            // X:\jsc.svn\examples\javascript\test\TestTypeHandle\TestTypeHandle\Application.cs

            #region stateTypeHandleIndex
            var stateTypeHandleIndex = default(object);
            var stateType            = default(Type);
            var state_ObjectData     = default(object);

            if (state != null)
            {
                stateType            = state.GetType();
                stateTypeHandleIndex = __Type.GetTypeIndex("state", stateType);
                var state_SerializableMembers = FormatterServices.GetSerializableMembers(stateType);
                // Failed to execute 'postMessage' on 'Worker': An object could not be cloned.
                state_ObjectData = FormatterServices.GetObjectData(state, state_SerializableMembers);
            }
            #endregion



            #region CreateWorker
            Action <string> CreateWorker = uri =>
            {
                // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20160108


                Console.WriteLine("enter CreateWorker");



                // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/201504/20150401
                // since we can start scope sharing, static sync may be turned off?

                #region xdata___string
                // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs
                dynamic xdata___string = new object();

                // how much does this slow us down?
                // connecting to a new scope, we need a fresh copy of everything
                // we can start with strings
                foreach (ExpandoMember nn in Expando.Of(InternalInlineWorker.__string).GetMembers())
                {
                    if (nn.Value != null)
                    {
                        xdata___string[nn.Name] = nn.Value;
                    }
                }
                #endregion


                var worker = new global::ScriptCoreLib.JavaScript.DOM.Worker(
                    uri
                    //InternalInlineWorker.GetScriptApplicationSourceForInlineWorker()
                    //global::ScriptCoreLib.JavaScript.DOM.Worker.ScriptApplicationSourceForInlineWorker
                    );


                // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2013/201309-1/20130904-iprogress

                // InternalInitializeInlineWorker { IsIProgress = false, state = [object Object] }
                // e = (a.state instanceof PWjgSJKGsjiGudzxTfGfaA);

                // jsc does not yet support is interface
                // function PWjgSJKGsjiGudzxTfGfaA() {}  PWjgSJKGsjiGudzxTfGfaA.TypeName = "IProgress_1";
                // we should add .Interfaces = []

                //Action<object> OnReportAction = default(__IProgress<object>).Report;
                //var OnReportMethod = OnReportAction.Method;


                // workaround until null as interface works.

                if (state == null)
                {
                    state = new object();
                }


                // what about delegates to the interface?
                #region IsIProgress
                var IsIProgress = state is __IProgress <object>;

                // InternalInitializeInlineWorker: { IsIProgress = true, state = [object Object] }
                var xProgress = default(__IProgress <object>);

                if (IsIProgress)
                {
                    // X:\jsc.svn\examples\javascript\async\test\TestWorkerProgress\TestWorkerProgress\Application.cs
                    xProgress            = (__IProgress <object>)state;
                    state                = null;
                    state_ObjectData     = null;
                    stateTypeHandleIndex = null;
                }
                #endregion

                //Console.WriteLine("InternalInitializeInlineWorker: " + new { IsIProgress, IsTuple2_Item1_IsIProgress, state });



                int responseCounter = 0;

                #region postMessage

                Console.WriteLine("before CreateWorker postMessage");

                // tested by
                // Z:\jsc.svn\examples\javascript\android\com.abstractatech.adminshell\com.abstractatech.adminshell\Application.cs


                var message = new
                {
                    InternalThreadCounter,


                    MethodTargetObjectDataIsProgress,

                    MethodTargetObjectData,

                    // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2014/201411/20141112
                    MethodTargetObjectDataTypes,

                    MethodTargetTypeIndex,

                    // set by ?
                    MethodToken,
                    MethodType,



                    // X:\jsc.svn\examples\javascript\test\TestTaskStartToString\TestTaskStartToString\Application.cs
                    // fields


                    // are we in state machine hop?
                    state_SerializableMembers = default(object),
                    state_ObjectData,

                    stateTypeHandleIndex,

                    state = state,


                    IsIProgress,
                    //IsTuple2_Item1_IsIProgress,

                    __string = (object)xdata___string
                };


                Console.WriteLine("before CreateWorker postMessage \n\n" + new { message });

                worker.postMessage(
                    message
                    ,
                    e =>
                {
                    responseCounter++;

                    // what kind of write backs do we expect?
                    // for now it should be console only


                    //Console.WriteLine(
                    //    "InternalInitializeInlineWorker: new message! "
                    //    + new
                    //    {
                    //        data = string.Join(
                    //           ", ",
                    //           Expando.Of(e.data).GetMemberNames().Select(k => (string)k).ToArray()
                    //        )
                    //    }
                    //);

                    // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs
                    dynamic zdata = e.data;


                    // is it the same for service worker?
                    #region AtWrite
                    string AtWrite = zdata.AtWrite;

                    if (!string.IsNullOrEmpty(AtWrite))
                    {
                        // thread is writing to console isnt it.
                        // we have requested to be notified of it on the main thread instead.

                        if (AtWrite.EndsWith("\r\n"))
                        {
                            Console.WriteLine(AtWrite.Substring(0, AtWrite.Length - 2));
                        }
                        else
                        {
                            Console.Write(AtWrite);
                        }
                    }
                    #endregion

                    #region __string
                    var zdata___string = (object)zdata.__string;
                    if (zdata___string != null)
                    {
                        #region __string
                        // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs
                        dynamic target = InternalInlineWorker.__string;
                        var m          = Expando.Of(zdata___string).GetMembers();

                        foreach (ExpandoMember nn in m)
                        {
                            Console.WriteLine("Worker has sent changes " + new { nn.Name });

                            target[nn.Name] = nn.Value;
                        }
                        #endregion
                    }
                    #endregion


                    //zdata.MethodTargetObjectDataProgressReport = new { ProgressEvent, i };

                    #region MethodTargetObjectDataProgressReport
                    {
                        // X:\jsc.svn\examples\javascript\async\test\TestWorkerScopeProgress\TestWorkerScopeProgress\Application.cs
                        // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs
                        dynamic MethodTargetObjectDataProgressReport = zdata.MethodTargetObjectDataProgressReport;
                        if ((object)MethodTargetObjectDataProgressReport != null)
                        {
                            object ProgressEvent = MethodTargetObjectDataProgressReport.ProgressEvent;
                            int ii = MethodTargetObjectDataProgressReport.ii;

                            MethodTargetObjectDataProgress[ii].Report(
                                ProgressEvent
                                );
                        }
                    }
                    #endregion


                    #region ContinueWithResult
                    {
                        // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs
                        dynamic ContinueWithResult = zdata.ContinueWithResult;
                        if ((object)ContinueWithResult != null)
                        {
                            responseCounter++;

                            // X:\jsc.svn\examples\javascript\async\test\TaskAsyncTaskRun\TaskAsyncTaskRun\Application.cs

                            var ResultTypeIndex  = default(object);
                            var ResultObjectData = default(object);

                            object Result = ContinueWithResult.Result;

                            // primitives wont have index
                            if (Result != null)
                            {
                                // X:\jsc.svn\examples\javascript\async\test\TestWorkerScopeProgress\TestWorkerScopeProgress\Application.cs

                                ResultTypeIndex  = ContinueWithResult.ResultTypeIndex;
                                ResultObjectData = ContinueWithResult.ResultObjectData;
                            }

                            // are we getting multiple responses?
                            Console.WriteLine("Task ContinueWithResult " + new { responseCounter, ResultTypeIndex, Result });

                            if (ResultTypeIndex != null)
                            {
                                // X:\jsc.svn\examples\javascript\async\test\TestTaskRunReturnToString\TestTaskRunReturnToString\Application.cs
                                // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs
                                dynamic self = Native.self;

                                var ResultType = Type.GetTypeFromHandle(new __RuntimeTypeHandle((IntPtr)self[ResultTypeIndex]));
                                var zResult    = FormatterServices.GetUninitializedObject(ResultType);
                                var zResultTypeSerializableMembers = FormatterServices.GetSerializableMembers(ResultType);


                                // available for flash too yet?
                                FormatterServices.PopulateObjectMembers(
                                    zResult,
                                    zResultTypeSerializableMembers,
                                    (object[])ResultObjectData
                                    );

                                var xResult = new TaskCompletionSource <object>();
                                //xResult.SetResult(Result);
                                xResult.SetResult(zResult);
                                this.InternalSetCompleteAndYield((TResult)(object)xResult.Task);
                            }
                            else
                            {
                                // :7170ms Task ContinueWithResult { ResultTypeIndex = type$rfUTAxaiVTOCOkKbE6i0hg }

                                //0:7506ms Task ContinueWithResult view-source:40742
                                //0:7508ms { Result = [object Object] }

                                var xResult = new TaskCompletionSource <object>();
                                //xResult.SetResult(Result);
                                xResult.SetResult(Result);
                                this.InternalSetCompleteAndYield((TResult)(object)xResult.Task);
                            }
                        }
                    }
                    #endregion


                    #region yield
                    {
                        // X:\jsc.svn\examples\javascript\async\AsyncHopToUIFromWorker\AsyncHopToUIFromWorker\Application.cs
                        // this should be disabled if we hopped to ui? how?
                        // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs
                        dynamic xyield = zdata.yield;
                        if ((object)xyield != null)
                        {
                            Console.WriteLine("worker sent a yield signal?");

                            object value = xyield.value;

                            // X:\jsc.svn\examples\javascript\async\test\TestSemaphoreSlimAwaitThenReleaseInWorker\TestSemaphoreSlimAwaitThenReleaseInWorker\Application.cs

                            Console.WriteLine("__Task.InternalStart inner complete (pre bugcheck) " + new { yield = new { value } });

                            // needs more tests.
                            // is causing trouble for older tests?

                            this.InternalDispose = delegate
                            {
                                Console.WriteLine("at InternalDispose");
                                worker.terminate();
                            };

                            this.InternalSetCompleteAndYield((TResult)value);



                            // when to terminate???
                            //w.terminate();
                        }
                    }
                    #endregion


                    #region __IProgress_Report
                    if (xProgress != null)
                    {
                        // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs
                        dynamic __IProgress_Report = zdata.__IProgress_Report;

                        if ((object)__IProgress_Report != null)
                        {
                            object value = __IProgress_Report.value;



                            //Console.WriteLine("InternalInitializeInlineWorker Report: " + new { __IProgress_Report = new { value } });


                            xProgress.Report(value);
                        }
                    }
                    #endregion


                    // X:\jsc.svn\examples\javascript\async\AsyncHopToUIFromWorker\AsyncHopToUIFromWorker\Application.cs
                    // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/201504/20150401
                    #region  HopToUIAwaitable
                    // where can we send the signal?

                    #endregion

                    if (yield != null)
                    {
                        yield(worker, e);
                    }
                }
                    );
                #endregion
            };
            #endregion



            #region InternalStart
            this.InternalStart = delegate
            {
                // X:\jsc.svn\examples\javascript\Test\TestRedirectWebWorker\TestRedirectWebWorker\Application.cs

                // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20160108
                Console.WriteLine("enter InternalStart");



                #region GetScriptApplicationSourceForInlineWorker
                var u = InternalInlineWorker.GetScriptApplicationSourceForInlineWorker();

                //GetScriptApplicationSourceForInlineWorker { value = view-source#worker }

                if (u == Worker.ScriptApplicationSource + "#worker")
                {
                    #region base not redirected
                    if (Native.document.baseURI == Native.document.location.href)
                    {
                        // X:\jsc.svn\examples\javascript\async\Test\TestDownloadStringTaskAsync\TestDownloadStringTaskAsync\Application.cs

                        // X:\jsc.svn\examples\javascript\test\TestTaskStartToString\TestTaskStartToString\Application.cs
                        //Console.WriteLine("Document base not redirected...");

                        // its about time to cache the inline worker source. if we have not done it before that is..

                        var sw = Stopwatch.StartNew();

                        if (InternalWorkerSourceToBlobCache.ContainsKey(u))
                        {
                            // in this case, lets continue in the blob..

                            UIWriteLine("worker source is in cache... pending");

                            InternalWorkerSourceToBlobCache[u].ContinueWith(
                                task =>
                            {
                                UIWriteLine("worker source is in cache... " + new { sw.ElapsedMilliseconds });


                                CreateWorker(task.Result);
                            }
                                );


                            return;
                        }

                        // otherwise lets download, once...
                        // X:\jsc.svn\examples\javascript\async\Test\TestBytesToSemaphore\TestBytesToSemaphore\Application.cs


                        UIWriteLine("will download worker source into cache...");

                        var pending = new TaskCompletionSource <string>();

                        InternalWorkerSourceToBlobCache[u] = pending.Task;


                        // 4.0 compatible, using 4.5 feats
                        new __WebClient().DownloadStringTaskAsync(u).ContinueWith(
                            task =>
                        {
                            UIWriteLine("will download worker source into cache... done " + new { task.Result.Length, sw.ElapsedMilliseconds });

                            var aFileParts = new[] { task.Result };
                            var oMyBlob    = new Blob(aFileParts, new { type = "text/javascript" });  // the blob
                            var url        = URL.createObjectURL(oMyBlob);

                            pending.SetResult(url);

                            CreateWorker(url);
                        }
                            );

                        return;
                    }
                    #endregion

                    // see also
                    // X:\jsc.svn\examples\javascript\chrome\extensions\ChromeExtensionWithWorker\ChromeExtensionWithWorker\Application.cs

                    {
                        // tested by?
                        Console.WriteLine("Document base redirected...");

                        var w = new WebClient();


                        // continue with?
                        w.DownloadStringCompleted +=
                            (sender, args) =>
                        {
                            var aFileParts = new[] { args.Result };
                            var oMyBlob    = new Blob(aFileParts, new { type = "text/javascript" });  // the blob
                            var url        = URL.createObjectURL(oMyBlob);

                            InternalInlineWorker.ScriptApplicationSourceForInlineWorker = url;

                            u = InternalInlineWorker.GetScriptApplicationSourceForInlineWorker();

                            CreateWorker(u);
                        };

                        // Failed to load resource: the server responded with a status of 400 (Bad Request) http://192.168.1.75:24275/:view-source
                        w.DownloadStringAsync(
                            new Uri(Worker.ScriptApplicationSource, UriKind.Relative)
                            );

                        return;
                    }
                }
                #endregion


                CreateWorker(u);
            };
            #endregion
        }
Пример #3
0
        public Task <TResult> ContinueWhenAll <TAntecedentResult, TResult>(
            Task <TAntecedentResult>[] tasks,
            Func <Task <TAntecedentResult>[], TResult> continuationFunction,
            CancellationToken cancellationToken,
            TaskContinuationOptions continuationOptions,
            TaskScheduler scheduler)
        {
            //Console.WriteLine("ContinueWhenAll " + new { tasks.Length, scheduler, Thread.CurrentThread.ManagedThreadId });


            var t = new __Task <TResult> {
                InternalStart = null
            };

            var cstart = 0;
            var cstop  = 0;

            #region ContinueWhenAll_yield
            Action ContinueWhenAll_yield = delegate
            {
                // how can we pass array of tasks to background?

                //Console.WriteLine("ContinueWhenAll_yield " + new { scheduler });

                #region GUI
                if (scheduler != null)
                {
                    var r = continuationFunction(tasks);

                    t.InternalSetCompleteAndYield(r);
                    return;
                }
                #endregion


                // X:\jsc.svn\examples\javascript\appengine\Test\AppEngineFirstEverWebServiceTask\AppEngineFirstEverWebServiceTask\ApplicationWebService.cs

                var xfunction  = continuationFunction;
                var MethodType = typeof(FuncOfTaskOfObjectArrayToObject).Name;

                #region MethodToken
                var MethodToken = ((__MethodInfo)xfunction.Method).InternalMethodToken;

                if (xfunction.Target != null)
                {
                    if (xfunction.Target != Native.self)
                    {
                        // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs
                        Delegate InternalTaskExtensionsScope_function = (xfunction.Target as dynamic).InternalTaskExtensionsScope_function;

                        if (InternalTaskExtensionsScope_function == null)
                        {
                            var message = "inline scope sharing not yet implemented";
                            Console.WriteLine(message);
                            throw new InvalidOperationException(message);
                        }

                        MethodToken = ((__MethodInfo)InternalTaskExtensionsScope_function.Method).InternalMethodToken;
                    }
                }
                #endregion



                #region xdata___string
                // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs
                dynamic xdata___string = new object();

                // how much does this slow us down?
                // connecting to a new scope, we need a fresh copy of everything
                // we can start with strings
                foreach (ExpandoMember nn in Expando.Of(InternalInlineWorker.__string).GetMembers())
                {
                    if (nn.Value != null)
                    {
                        xdata___string[nn.Name] = nn.Value;
                    }
                }
                #endregion

                // is this correct?
                // OBSOLETE ! needs more tests. what about scope sharing?
                var w = new global::ScriptCoreLib.JavaScript.DOM.Worker(
                    InternalInlineWorker.GetScriptApplicationSourceForInlineWorker()
                    //global::ScriptCoreLib.JavaScript.DOM.Worker.ScriptApplicationSourceForInlineWorker
                    );

                var TaskArray = tasks.Select(k => new { k.Result }).ToArray();

                Console.WriteLine(new { TaskArray = TaskArray.Length });
                //Debugger.Break();


                #region postMessage
                w.postMessage(
                    new
                {
                    InternalInlineWorker.InternalThreadCounter,
                    MethodToken,
                    MethodType,

                    //state = state,

                    // pass the result for reconstruction

                    // task[0].Result

                    TaskArray,

                    __string = (object)xdata___string
                }
                    ,
                    e =>
                {
                    // what kind of write backs do we expect?
                    // for now it should be console only

                    // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs
                    dynamic zdata = e.data;

                    #region AtWrite
                    string AtWrite = zdata.AtWrite;

                    if (!string.IsNullOrEmpty(AtWrite))
                    {
                        Console.Write(AtWrite);
                    }
                    #endregion

                    #region __string
                    var zdata___string = (object)zdata.__string;
                    if (zdata___string != null)
                    {
                        #region __string
                        dynamic target = InternalInlineWorker.__string;
                        var m          = Expando.Of(zdata___string).GetMembers();

                        foreach (ExpandoMember nn in m)
                        {
                            Console.WriteLine("Worker has sent changes " + new { nn.Name });

                            target[nn.Name] = nn.Value;
                        }
                        #endregion
                    }
                    #endregion

                    #region yield
                    dynamic yield = zdata.yield;
                    if ((object)yield != null)
                    {
                        object value = yield.value;

                        //Console.WriteLine("__Task.InternalStart inner complete " + new { yield = new { value } });


                        t.InternalSetCompleteAndYield((TResult)value);

                        //w.terminate();
                    }
                    #endregion
                }
                    );
                #endregion

                InternalInlineWorker.InternalThreadCounter++;
            };
            #endregion


            #region ContinueWhenAll_yield
            foreach (__Task <TAntecedentResult> item in tasks)
            {
                cstart++;
                //Console.WriteLine("ContinueWhenAll before ContinueWith " + new { cstart, tasks.Length, Thread.CurrentThread.ManagedThreadId });

                item.ContinueWith(
                    task =>
                {
                    cstop++;
                    //Console.WriteLine("ContinueWhenAll ContinueWith yield " + new { cstop, tasks.Length, Thread.CurrentThread.ManagedThreadId });


                    if (cstop == tasks.Length)
                    {
                        //Console.WriteLine("before ContinueWhenAll_yield");

                        ContinueWhenAll_yield();
                        //Console.WriteLine("after ContinueWhenAll_yield");
                    }
                },

                    // just for the watchdog
                    scheduler: TaskScheduler.FromCurrentSynchronizationContext()
                    );
            }
            #endregion

            return(t);
        }