Ejemplo n.º 1
0
        /// <summary>
        /// Creates a new Promise instance from a task.
        /// </summary>
        /// <param name="task"> A task to wait on. </param>
        /// <returns> The Promise instance. </returns>
        /// <remarks>
        /// If the task is of type Task&lt;object&gt; then the result of the task will be used to
        /// resolve the promise. Otherwise, the promise is resolved with "undefined" as the value.
        /// </remarks>
        public PromiseInstance FromTask(Task task)
        {
            if (task == null)
            {
                throw new ArgumentNullException(nameof(task));
            }

            // Create a new promise.
            var promise = new PromiseInstance(this.InstancePrototype);

            // Execute some code after the task completes.
            task.ConfigureAwait(continueOnCapturedContext: false).GetAwaiter().OnCompleted(() =>
            {
                // Enqueue an event which resolves the promise.
                Engine.EnqueueEvent(() =>
                {
                    try
                    {
                        if (task is Task <object> objectTask)
                        {
                            promise.Resolve(objectTask.Result);
                        }
                        else
                        {
                            promise.Resolve(Undefined.Value);
                        }
                    }
                    catch (AggregateException ex)
                    {
                        if (ex.InnerExceptions.Count == 1)
                        {
                            var innerException = ex.InnerExceptions[0];
                            if (innerException is JavaScriptException innerJSException)
                            {
                                promise.Reject(innerJSException.GetErrorObject(Engine));
                            }
                            else
                            {
                                promise.Reject(innerException.Message);
                            }
                        }
                        else
                        {
                            promise.Reject(ex.Message);
                        }
                    }
                    catch (JavaScriptException ex)
                    {
                        promise.Reject(ex.GetErrorObject(Engine));
                    }
                    catch (Exception ex)
                    {
                        promise.Reject(ex.Message);
                    }
                });
            });

            return(promise);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Creates a new Promise instance.
        /// </summary>
        /// <param name="notify">A <see cref="INotifyCompletion"/> that will signal the success or failure of the promise.</param>
        /// <returns>The Promise instance.</returns>
        public PromiseInstance Construct <T>(T notify)
            where T : INotifyCompletion
        {
            var promise = new PromiseInstance(this.InstancePrototype);

            if (notify == null)
            {
                return(promise);
            }

            notify.OnCompleted(() =>
            {
                try
                {
                    promise.Resolve(TaskAwaiterCache.GetResult(notify));
                }
                catch (JavaScriptException jex)
                {
                    promise.Reject(jex.ErrorObject);
                }
                catch (Exception e)
                {
                    promise.Reject(e.Message);
                }
            });

            return(promise);
        }
        public PromiseInstance Resolve(object result)
        {
            var promise = new PromiseInstance(this.InstancePrototype);

            promise.Resolve(result);
            return(promise);
        }
Ejemplo n.º 4
0
        public PromiseInstance Resolve(object value)
        {
            // If the constructor of value === this, then return as is.
            if (value is PromiseInstance promise)
            {
                return(promise);
            }

            var result = new PromiseInstance(this.InstancePrototype);

            result.Resolve(value);
            return(result);
        }
        public PromiseInstance Race(ObjectInstance iterable)
        {
            if (iterable == null)
            {
                throw new JavaScriptException(iterable.Engine, ErrorType.TypeError, "The parameter must be an iterable.");
            }

            var iterator = TypeUtilities.GetIterator(iterable.Engine, iterable);
            var promises = TypeUtilities.Iterate(iterator.Engine, iterator);

            var promise = new PromiseInstance(iterable.Engine.Promise.InstancePrototype);

            foreach (var promiseOrValue in promises)
            {
                if (promise.State != PromiseState.Pending)
                {
                    break;
                }
                promise.Resolve(promiseOrValue);
            }

            return(promise);
        }
Ejemplo n.º 6
0
        public PromiseInstance All(ObjectInstance iterable)
        {
            if (iterable == null)
            {
                throw new JavaScriptException(iterable.Engine, ErrorType.TypeError, "The parameter must be an iterable.");
            }

            var iterator = TypeUtilities.GetIterator(iterable.Engine, iterable);
            var promises = TypeUtilities.Iterate(iterator.Engine, iterator).ToList();
            var results  = Engine.Array.Construct(new object[promises.Count]);
            var count    = promises.Count;

            var promise = new PromiseInstance(iterable.Engine.Promise.InstancePrototype);

            // The promise is resolved immediately if the iterable is empty.
            if (promises.Count == 0)
            {
                promise.Resolve(results);
                return(promise);
            }

            for (var i = 0; i < promises.Count; i++)
            {
                if (promise.State != PromiseState.Pending)
                {
                    break;
                }

                if (promises[i] is PromiseInstance p)
                {
                    if (p.State == PromiseState.Rejected)
                    {
                        promise.Reject(p.Result);
                        break;
                    }
                    else if (p.State == PromiseState.Fulfilled)
                    {
                        results[i] = p.Result;
                        if (--count == 0)
                        {
                            promise.Resolve(results);
                            break;
                        }
                        continue;
                    }

                    var j = i; // Some C# versions need this.
                    p.Then(new ClrStubFunction(Engine.FunctionInstancePrototype, "", 1, (engine, thisObj, args) =>
                    {
                        if (promise.State != PromiseState.Pending)
                        {
                            return(Undefined.Value);
                        }

                        results[j] = args[0];

                        if (--count == 0)
                        {
                            promise.Resolve(results);
                        }
                        return(Undefined.Value);
                    }),
                           new ClrStubFunction(Engine.FunctionInstancePrototype, "", 1, (engine, thisObj, args) =>
                    {
                        promise.Reject(args[0]);
                        return(Undefined.Value);
                    }));

                    continue;
                }
                else if (promises[i] is ObjectInstance obj && obj.HasProperty("then"))
                {
                    FunctionInstance then;
                    try
                    {
                        then = obj.GetPropertyValue("then") as FunctionInstance;
                    }
                    catch (JavaScriptException jex)
                    {
                        promise.Reject(jex.ErrorObject);
                        break;
                    }

                    if (then != null)
                    {
                        try
                        {
                            var j       = i; // Some C# versions need this.
                            var resolve = new ClrStubFunction(iterable.Engine.Function.InstancePrototype, (engine, ths, arg) =>
                            {
                                if (promise.State != PromiseState.Pending)
                                {
                                    return(Undefined.Value);
                                }

                                results[j] = arg.Length == 0
                                    ? Undefined.Value
                                    : arg[0];

                                if (--count == 0)
                                {
                                    promise.Resolve(results);
                                }
                                return(Undefined.Value);
                            });

                            then.Call(obj, resolve, promise.RejectFunction);
                            continue;
                        }
                        catch (JavaScriptException jex)
                        {
                            promise.Reject(jex.ErrorObject);
                            break;
                        }
                    }
                }

                results[i] = promises[i];
                if (--count == 0)
                {
                    promise.Resolve(results);
                    break;
                }
            }

            return(promise);
        }