| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2014 Google Inc. All rights reserved. | 2 * Copyright (C) 2014 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 #include "bindings/v8/ScriptPromise.h" | 32 #include "bindings/v8/ScriptPromise.h" |
| 33 | 33 |
| 34 #include "RuntimeEnabledFeatures.h" | 34 #include "bindings/v8/ScriptFunction.h" |
| 35 #include "bindings/v8/DOMWrapperWorld.h" | |
| 36 #include "bindings/v8/ScriptPromiseResolver.h" | 35 #include "bindings/v8/ScriptPromiseResolver.h" |
| 37 #include "bindings/v8/ScriptValue.h" | 36 #include "bindings/v8/ScriptValue.h" |
| 38 #include "bindings/v8/V8Binding.h" | 37 #include "bindings/v8/V8Binding.h" |
| 39 #include "bindings/v8/custom/V8PromiseCustom.h" | |
| 40 | 38 |
| 41 #include <gtest/gtest.h> | 39 #include <gtest/gtest.h> |
| 42 #include <v8.h> | 40 #include <v8.h> |
| 43 | 41 |
| 44 namespace WebCore { | 42 namespace WebCore { |
| 45 | 43 |
| 46 namespace { | 44 namespace { |
| 47 | 45 |
| 48 void callback(const v8::FunctionCallbackInfo<v8::Value>& info) { } | 46 void callback(const v8::FunctionCallbackInfo<v8::Value>& info) { } |
| 49 | 47 |
| 48 class Function : public ScriptFunction { |
| 49 public: |
| 50 static PassOwnPtr<Function> create(v8::Isolate* isolate, String* value) |
| 51 { |
| 52 return adoptPtr(new Function(isolate, value)); |
| 53 } |
| 54 |
| 55 virtual ScriptValue call(ScriptValue value) OVERRIDE |
| 56 { |
| 57 ASSERT(!value.isEmpty()); |
| 58 *m_value = toCoreString(value.v8Value()->ToString()); |
| 59 return value; |
| 60 } |
| 61 |
| 62 private: |
| 63 Function(v8::Isolate* isolate, String* value) : ScriptFunction(isolate), m_v
alue(value) { } |
| 64 |
| 65 String* m_value; |
| 66 }; |
| 67 |
| 50 class ScriptPromiseTest : public testing::Test { | 68 class ScriptPromiseTest : public testing::Test { |
| 51 public: | 69 public: |
| 52 ScriptPromiseTest() | 70 ScriptPromiseTest() |
| 53 : m_scope(V8ExecutionScope::create(v8::Isolate::GetCurrent())) | 71 : m_scope(V8ExecutionScope::create(v8::Isolate::GetCurrent())) |
| 54 { | 72 { |
| 55 } | 73 } |
| 56 | 74 |
| 57 ~ScriptPromiseTest() | 75 ~ScriptPromiseTest() |
| 58 { | 76 { |
| 59 // FIXME: We put this statement here to clear an exception from the isol
ate. | 77 // FIXME: We put this statement here to clear an exception from the isol
ate. |
| 60 createClosure(callback, v8::Undefined(m_scope->isolate()), m_scope->isol
ate()); | 78 createClosure(callback, v8::Undefined(m_scope->isolate()), m_scope->isol
ate()); |
| 79 |
| 80 // Execute all pending microtasks |
| 81 isolate()->RunMicrotasks(); |
| 61 } | 82 } |
| 62 | 83 |
| 63 V8PromiseCustom::PromiseState state(ScriptPromise promise) | 84 ScriptState* scriptState() { return m_scope->scriptState(); } |
| 64 { | 85 v8::Isolate* isolate() { return m_scope->isolate(); } |
| 65 return V8PromiseCustom::getState(V8PromiseCustom::getInternal(promise.v8
Value().As<v8::Object>())); | |
| 66 } | |
| 67 | 86 |
| 68 protected: | 87 protected: |
| 69 OwnPtr<V8ExecutionScope> m_scope; | 88 OwnPtr<V8ExecutionScope> m_scope; |
| 70 }; | 89 }; |
| 71 | 90 |
| 72 TEST_F(ScriptPromiseTest, constructFromNonPromise) | 91 TEST_F(ScriptPromiseTest, constructFromNonPromise) |
| 73 { | 92 { |
| 74 v8::TryCatch trycatch; | 93 v8::TryCatch trycatch; |
| 75 ScriptPromise promise(m_scope->scriptState(), v8::Undefined(m_scope->isolate
())); | 94 ScriptPromise promise(scriptState(), v8::Undefined(isolate())); |
| 76 ASSERT_TRUE(trycatch.HasCaught()); | 95 ASSERT_TRUE(trycatch.HasCaught()); |
| 77 ASSERT_TRUE(promise.isEmpty()); | 96 ASSERT_TRUE(promise.isEmpty()); |
| 78 } | 97 } |
| 79 | 98 |
| 99 TEST_F(ScriptPromiseTest, thenResolve) |
| 100 { |
| 101 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scrip
tState()); |
| 102 ScriptPromise promise = resolver->promise(); |
| 103 String onFulfilled, onRejected; |
| 104 promise.then(Function::create(isolate(), &onFulfilled), Function::create(iso
late(), &onRejected)); |
| 105 |
| 106 ASSERT_FALSE(promise.isEmpty()); |
| 107 EXPECT_EQ(String(), onFulfilled); |
| 108 EXPECT_EQ(String(), onRejected); |
| 109 |
| 110 isolate()->RunMicrotasks(); |
| 111 resolver->resolve("hello"); |
| 112 |
| 113 EXPECT_EQ(String(), onFulfilled); |
| 114 EXPECT_EQ(String(), onRejected); |
| 115 |
| 116 isolate()->RunMicrotasks(); |
| 117 |
| 118 EXPECT_EQ("hello", onFulfilled); |
| 119 EXPECT_EQ(String(), onRejected); |
| 120 } |
| 121 |
| 122 TEST_F(ScriptPromiseTest, resolveThen) |
| 123 { |
| 124 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scrip
tState()); |
| 125 ScriptPromise promise = resolver->promise(); |
| 126 String onFulfilled, onRejected; |
| 127 resolver->resolve("hello"); |
| 128 promise.then(Function::create(isolate(), &onFulfilled), Function::create(iso
late(), &onRejected)); |
| 129 |
| 130 ASSERT_FALSE(promise.isEmpty()); |
| 131 EXPECT_EQ(String(), onFulfilled); |
| 132 EXPECT_EQ(String(), onRejected); |
| 133 |
| 134 isolate()->RunMicrotasks(); |
| 135 |
| 136 EXPECT_EQ("hello", onFulfilled); |
| 137 EXPECT_EQ(String(), onRejected); |
| 138 } |
| 139 |
| 140 TEST_F(ScriptPromiseTest, thenReject) |
| 141 { |
| 142 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scrip
tState()); |
| 143 ScriptPromise promise = resolver->promise(); |
| 144 String onFulfilled, onRejected; |
| 145 promise.then(Function::create(isolate(), &onFulfilled), Function::create(iso
late(), &onRejected)); |
| 146 |
| 147 ASSERT_FALSE(promise.isEmpty()); |
| 148 EXPECT_EQ(String(), onFulfilled); |
| 149 EXPECT_EQ(String(), onRejected); |
| 150 |
| 151 isolate()->RunMicrotasks(); |
| 152 resolver->reject("hello"); |
| 153 |
| 154 EXPECT_EQ(String(), onFulfilled); |
| 155 EXPECT_EQ(String(), onRejected); |
| 156 |
| 157 isolate()->RunMicrotasks(); |
| 158 |
| 159 EXPECT_EQ(String(), onFulfilled); |
| 160 EXPECT_EQ("hello", onRejected); |
| 161 } |
| 162 |
| 163 TEST_F(ScriptPromiseTest, rejectThen) |
| 164 { |
| 165 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scrip
tState()); |
| 166 ScriptPromise promise = resolver->promise(); |
| 167 String onFulfilled, onRejected; |
| 168 resolver->reject("hello"); |
| 169 promise.then(Function::create(isolate(), &onFulfilled), Function::create(iso
late(), &onRejected)); |
| 170 |
| 171 ASSERT_FALSE(promise.isEmpty()); |
| 172 EXPECT_EQ(String(), onFulfilled); |
| 173 EXPECT_EQ(String(), onRejected); |
| 174 |
| 175 isolate()->RunMicrotasks(); |
| 176 |
| 177 EXPECT_EQ(String(), onFulfilled); |
| 178 EXPECT_EQ("hello", onRejected); |
| 179 } |
| 180 |
| 80 TEST_F(ScriptPromiseTest, castPromise) | 181 TEST_F(ScriptPromiseTest, castPromise) |
| 81 { | 182 { |
| 82 if (RuntimeEnabledFeatures::scriptPromiseOnV8PromiseEnabled()) | 183 ScriptPromise promise = ScriptPromiseResolver::create(scriptState())->promis
e(); |
| 83 return; | 184 ScriptPromise newPromise = ScriptPromise::cast(scriptState(), promise.v8Valu
e()); |
| 84 ScriptPromise promise = ScriptPromiseResolver::create(m_scope->scriptState()
)->promise(); | |
| 85 ScriptPromise newPromise = ScriptPromise::cast(ScriptValue(m_scope->scriptSt
ate(), promise.v8Value())); | |
| 86 | 185 |
| 87 ASSERT_FALSE(promise.isEmpty()); | 186 ASSERT_FALSE(promise.isEmpty()); |
| 88 EXPECT_EQ(V8PromiseCustom::Pending, state(promise)); | |
| 89 EXPECT_EQ(promise.v8Value(), newPromise.v8Value()); | 187 EXPECT_EQ(promise.v8Value(), newPromise.v8Value()); |
| 90 } | 188 } |
| 91 | 189 |
| 92 TEST_F(ScriptPromiseTest, castNonPromise) | 190 TEST_F(ScriptPromiseTest, castNonPromise) |
| 93 { | 191 { |
| 94 if (RuntimeEnabledFeatures::scriptPromiseOnV8PromiseEnabled()) | 192 String onFulfilled1, onFulfilled2, onRejected1, onRejected2; |
| 95 return; | 193 |
| 96 ScriptValue value = ScriptValue(m_scope->scriptState(), v8String(m_scope->is
olate(), "hello")); | 194 ScriptValue value = ScriptValue(scriptState(), v8String(isolate(), "hello"))
; |
| 97 ScriptPromise promise1 = ScriptPromise::cast(ScriptValue(value)); | 195 ScriptPromise promise1 = ScriptPromise::cast(ScriptValue(value)); |
| 98 ScriptPromise promise2 = ScriptPromise::cast(ScriptValue(value)); | 196 ScriptPromise promise2 = ScriptPromise::cast(ScriptValue(value)); |
| 197 promise1.then(Function::create(isolate(), &onFulfilled1), Function::create(i
solate(), &onRejected1)); |
| 198 promise2.then(Function::create(isolate(), &onFulfilled2), Function::create(i
solate(), &onRejected2)); |
| 99 | 199 |
| 100 ASSERT_FALSE(promise1.isEmpty()); | 200 ASSERT_FALSE(promise1.isEmpty()); |
| 101 ASSERT_FALSE(promise2.isEmpty()); | 201 ASSERT_FALSE(promise2.isEmpty()); |
| 202 EXPECT_NE(promise1.v8Value(), promise2.v8Value()); |
| 102 | 203 |
| 103 ASSERT_TRUE(V8PromiseCustom::isPromise(promise1.v8Value(), m_scope->isolate(
))); | 204 ASSERT_TRUE(promise1.v8Value()->IsPromise()); |
| 104 ASSERT_TRUE(V8PromiseCustom::isPromise(promise2.v8Value(), m_scope->isolate(
))); | 205 ASSERT_TRUE(promise2.v8Value()->IsPromise()); |
| 105 | 206 |
| 106 EXPECT_EQ(V8PromiseCustom::Fulfilled, state(promise1)); | 207 EXPECT_EQ(String(), onFulfilled1); |
| 107 EXPECT_EQ(V8PromiseCustom::Fulfilled, state(promise2)); | 208 EXPECT_EQ(String(), onFulfilled2); |
| 108 EXPECT_NE(promise1.v8Value(), promise2.v8Value()); | 209 EXPECT_EQ(String(), onRejected1); |
| 210 EXPECT_EQ(String(), onRejected2); |
| 211 |
| 212 isolate()->RunMicrotasks(); |
| 213 |
| 214 EXPECT_EQ("hello", onFulfilled1); |
| 215 EXPECT_EQ("hello", onFulfilled2); |
| 216 EXPECT_EQ(String(), onRejected1); |
| 217 EXPECT_EQ(String(), onRejected2); |
| 218 } |
| 219 |
| 220 TEST_F(ScriptPromiseTest, reject) |
| 221 { |
| 222 String onFulfilled, onRejected; |
| 223 |
| 224 ScriptValue value = ScriptValue(scriptState(), v8String(isolate(), "hello"))
; |
| 225 ScriptPromise promise = ScriptPromise::reject(ScriptValue(value)); |
| 226 promise.then(Function::create(isolate(), &onFulfilled), Function::create(iso
late(), &onRejected)); |
| 227 |
| 228 ASSERT_FALSE(promise.isEmpty()); |
| 229 ASSERT_TRUE(promise.v8Value()->IsPromise()); |
| 230 |
| 231 EXPECT_EQ(String(), onFulfilled); |
| 232 EXPECT_EQ(String(), onRejected); |
| 233 |
| 234 isolate()->RunMicrotasks(); |
| 235 |
| 236 EXPECT_EQ(String(), onFulfilled); |
| 237 EXPECT_EQ("hello", onRejected); |
| 109 } | 238 } |
| 110 | 239 |
| 111 } // namespace | 240 } // namespace |
| 112 | 241 |
| 113 } // namespace WebCore | 242 } // namespace WebCore |
| OLD | NEW |