forked from ClearFoundry/ClearScript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJavaScriptExtensions.cs
More file actions
136 lines (119 loc) · 6.04 KB
/
JavaScriptExtensions.cs
File metadata and controls
136 lines (119 loc) · 6.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.Threading.Tasks;
using Microsoft.ClearScript.Util;
namespace Microsoft.ClearScript.JavaScript
{
/// <summary>
/// Defines extension methods for use with JavaScript engines.
/// </summary>
public static class JavaScriptExtensions
{
private delegate void Executor(object resolve, object reject);
/// <summary>
/// Converts a <see cref="Task{TResult}"/> instance to a
/// <see href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promise</see>
/// for use with script code currently running on the calling thread.
/// </summary>
/// <typeparam name="TResult">The task's result type.</typeparam>
/// <param name="task">The task to convert to a promise.</param>
/// <returns>A promise that represents the task's asynchronous operation.</returns>
public static object ToPromise<TResult>(this Task<TResult> task)
{
return task.ToPromise(ScriptEngine.Current);
}
/// <summary>
/// Converts a <see cref="Task{TResult}"/> instance to a
/// <see href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promise</see>
/// for use with script code running in the specified script engine.
/// </summary>
/// <typeparam name="TResult">The task's result type.</typeparam>
/// <param name="task">The task to convert to a promise.</param>
/// <param name="engine">The script engine in which the promise will be used.</param>
/// <returns>A promise that represents the task's asynchronous operation.</returns>
public static object ToPromise<TResult>(this Task<TResult> task, ScriptEngine engine)
{
MiscHelpers.VerifyNonNullArgument(task, "task");
MiscHelpers.VerifyNonNullArgument(engine, "engine");
var javaScriptEngine = engine as IJavaScriptEngine;
if ((javaScriptEngine == null) || (javaScriptEngine.BaseLanguageVersion < 6))
{
throw new NotSupportedException("The script engine does not support promises");
}
return engine.Script.EngineInternal.createPromise(new Executor((resolve, reject) =>
{
Action<Task> continuation = thisTask => engine.Script.EngineInternal.onTaskWithResultCompleted(thisTask, resolve, reject);
task.ContinueWith(continuation, TaskContinuationOptions.ExecuteSynchronously);
}));
}
/// <summary>
/// Converts a <see cref="Task"/> instance to a
/// <see href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promise</see>
/// for use with script code currently running on the calling thread.
/// </summary>
/// <param name="task">The task to convert to a promise.</param>
/// <returns>A promise that represents the task's asynchronous operation.</returns>
public static object ToPromise(this Task task)
{
return task.ToPromise(ScriptEngine.Current);
}
/// <summary>
/// Converts a <see cref="Task"/> instance to a
/// <see href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promise</see>
/// for use with script code running in the specified script engine.
/// </summary>
/// <param name="task">The task to convert to a promise.</param>
/// <param name="engine">The script engine in which the promise will be used.</param>
/// <returns>A promise that represents the task's asynchronous operation.</returns>
public static object ToPromise(this Task task, ScriptEngine engine)
{
MiscHelpers.VerifyNonNullArgument(task, "task");
MiscHelpers.VerifyNonNullArgument(engine, "engine");
var javaScriptEngine = engine as IJavaScriptEngine;
if ((javaScriptEngine == null) || (javaScriptEngine.BaseLanguageVersion < 6))
{
throw new NotSupportedException("The script engine does not support promises");
}
return engine.Script.EngineInternal.createPromise(new Executor((resolve, reject) =>
{
Action<Task> continuation = thisTask => engine.Script.EngineInternal.onTaskCompleted(thisTask, resolve, reject);
task.ContinueWith(continuation, TaskContinuationOptions.ExecuteSynchronously);
}));
}
/// <summary>
/// Converts a
/// <see href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promise</see>
/// to a <see cref="Task{Object}"/> instance.
/// </summary>
/// <param name="promise">The promise to convert to a task.</param>
/// <returns>A task that represents the promise's asynchronous operation.</returns>
public static Task<object> ToTask(this object promise)
{
MiscHelpers.VerifyNonNullArgument(promise, "promise");
var scriptObject = promise as ScriptObject;
if ((scriptObject == null) || !scriptObject.Engine.Script.EngineInternal.isPromise(promise))
{
throw new ArgumentException("The object is not a promise", "promise");
}
var source = new TaskCompletionSource<object>();
Action<object> onResolved = result =>
{
source.SetResult(result);
};
Action<object> onRejected = error =>
{
try
{
scriptObject.Engine.Script.EngineInternal.throwValue(error);
}
catch (Exception exception)
{
source.SetException(exception);
}
};
((dynamic)promise).then(onResolved, onRejected);
return source.Task;
}
}
}