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
use chakracore_sys::*;
use context::ContextGuard;
use super::{Value, Object, Function};
use error::*;
use Context;
pub struct Executor {
resolve: Function,
reject: Function,
}
impl Executor {
pub fn resolve(self, guard: &ContextGuard, arguments: &[&Value]) -> Result<()> {
self.resolve.call(guard, arguments).map(|_| ())
}
pub fn reject(self, guard: &ContextGuard, arguments: &[&Value]) -> Result<()> {
self.reject.call(guard, arguments).map(|_| ())
}
}
pub struct Promise(JsValueRef);
impl Promise {
pub fn new(_guard: &ContextGuard) -> (Self, Executor) {
let mut reference = JsValueRef::new();
let mut resolve = JsValueRef::new();
let mut reject = JsValueRef::new();
unsafe {
jsassert!(JsCreatePromise(&mut reference, &mut resolve, &mut reject));
(Self::from_raw(reference), Executor {
resolve: Function::from_raw(resolve),
reject: Function::from_raw(reject)
})
}
}
pub fn is_same(value: &Value) -> bool {
value.clone().into_object().map_or(false, |object| {
Context::exec_with_value(&object, |guard| {
let promise = ::script::eval(guard, "Promise")
.expect("retrieving Promise constructor")
.into_function()
.expect("converting Promise to function");
promise.instance_of(guard, &object)
})
.expect("changing active context for Promise comparison")
.expect("missing associated context for Promise comparison")
})
}
}
reference!(Promise);
inherit!(Promise, Object);
subtype!(Promise, Value);
#[cfg(test)]
mod tests {
use {test, value, script, Property};
#[test]
fn resolve() {
test::run_with_context(|guard| {
let (promise, executor) = value::Promise::new(guard);
executor.resolve(guard, &[&value::Number::new(guard, 10)]).unwrap();
let global = guard.global();
let property = Property::new(guard, "promise");
global.set(guard, &property, &promise);
let result = script::eval(guard, "
var result = {};
promise.then(function(value) { result.val = value; });
result")
.unwrap()
.into_object()
.unwrap();
guard.execute_tasks();
assert_eq!(result.get(guard, &Property::new(guard, "val")).to_integer(guard), 10);
});
}
#[test]
fn conversion() {
test::run_with_context(|guard| {
let (promise, _) = value::Promise::new(guard);
let value: value::Value = promise.into();
assert!(value.into_promise().is_some());
let promise = script::eval(guard, "new Promise(() => {})")
.unwrap()
.into_promise();
assert!(promise.is_some());
});
}
}