Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: Source/bindings/core/v8/ScriptPromisePropertyTest.cpp

Issue 361863003: Add a helper for implementing Promise-valued properties. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Remove a RefCountedWillBeGarbageCollected. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "bindings/core/v8/ScriptPromiseProperty.h"
7
8 #include "bindings/core/v8/DOMWrapperWorld.h"
9 #include "bindings/core/v8/ScriptFunction.h"
10 #include "bindings/core/v8/ScriptPromise.h"
11 #include "bindings/core/v8/ScriptState.h"
12 #include "bindings/core/v8/ScriptValue.h"
13 #include "bindings/core/v8/V8Binding.h"
14 #include "core/dom/Document.h"
15 #include "core/events/Event.h"
16 #include "core/testing/DummyPageHolder.h"
17 #include "core/testing/GCObservation.h"
18 #include "wtf/OwnPtr.h"
19 #include "wtf/PassOwnPtr.h"
20 #include "wtf/PassRefPtr.h"
21 #include "wtf/RefPtr.h"
22 #include <gtest/gtest.h>
23 #include <v8.h>
24
25 using namespace WebCore;
26
27 namespace {
28
29 class NotReached : public ScriptFunction {
30 public:
31 NotReached() : ScriptFunction(v8::Isolate::GetCurrent()) { }
32
33 private:
34 virtual ScriptValue call(ScriptValue) OVERRIDE;
35 };
36
37 ScriptValue NotReached::call(ScriptValue)
38 {
39 EXPECT_TRUE(false) << "'Unreachable' code was reached";
40 return ScriptValue();
41 }
42
43 class StubFunction : public ScriptFunction {
44 public:
45 StubFunction(ScriptValue&, size_t& callCount);
46
47 private:
48 virtual ScriptValue call(ScriptValue) OVERRIDE;
49
50 ScriptValue& m_value;
51 size_t& m_callCount;
52 };
53
54 StubFunction::StubFunction(ScriptValue& value, size_t& callCount)
55 : ScriptFunction(v8::Isolate::GetCurrent())
56 , m_value(value)
57 , m_callCount(callCount)
58 {
59 }
60
61 ScriptValue StubFunction::call(ScriptValue arg)
62 {
63 m_value = arg;
64 m_callCount++;
65 return ScriptValue();
66 }
67
68 class ScriptPromisePropertyTest : public ::testing::Test {
69 protected:
70 ScriptPromisePropertyTest()
71 : m_page(DummyPageHolder::create(IntSize(1, 1)))
72 {
73 }
74
75 virtual ~ScriptPromisePropertyTest() { destroyContext(); }
76
77 Document& document() { return m_page->document(); }
78 v8::Isolate* isolate() { return toIsolate(&document()); }
79 ScriptState* scriptState() { return ScriptState::forMainWorld(document().fra me()); }
80
81 void destroyContext()
82 {
83 m_page.clear();
84 gc();
85 }
86
87 void gc() { v8::Isolate::GetCurrent()->RequestGarbageCollectionForTesting(v8 ::Isolate::kFullGarbageCollection); }
88
89 PassOwnPtr<ScriptFunction> notReached() { return adoptPtr(new NotReached()); }
90 PassOwnPtr<ScriptFunction> stub(ScriptValue& value, size_t& callCount) { ret urn adoptPtr(new StubFunction(value, callCount)); }
91
92 // These tests use Event because it is simple to manufacture lots of events.
93
94 ScriptValue wrap(PassRefPtr<Event> event)
95 {
96 ScriptState::Scope scope(scriptState());
97 return ScriptValue(scriptState(), V8ValueTraits<Event>::toV8Value(event, scriptState()->context()->Global(), isolate()));
98 }
99
100 typedef ScriptPromiseProperty<RefPtr<Event>, Event*, Event*> Property;
101 PassRefPtr<Property> newProperty() { return Property::create(&document(), Ev ent::create(), "test"); }
102
103 private:
104 OwnPtr<DummyPageHolder> m_page;
105 };
106
107 TEST_F(ScriptPromisePropertyTest, Promise_IsStableObject)
108 {
109 RefPtr<Property> p(newProperty());
110 ScriptPromise v = p->promise(DOMWrapperWorld::mainWorld());
111 ScriptPromise w = p->promise(DOMWrapperWorld::mainWorld());
112 EXPECT_EQ(v, w);
113 EXPECT_FALSE(v.isEmpty());
114 EXPECT_EQ(Property::Pending, p->state());
115 }
116
117 TEST_F(ScriptPromisePropertyTest, Promise_IsStableObjectAfterSettling)
118 {
119 RefPtr<Property> p(newProperty());
120 ScriptPromise v = p->promise(DOMWrapperWorld::mainWorld());
121
122 RefPtr<Event> value(Event::create());
123 p->resolve(value.get());
124 EXPECT_EQ(Property::Resolved, p->state());
125
126 ScriptPromise w = p->promise(DOMWrapperWorld::mainWorld());
127 EXPECT_EQ(v, w);
128 EXPECT_FALSE(v.isEmpty());
129 }
130
131 TEST_F(ScriptPromisePropertyTest, Promise_DoesNotImpedeGarbageCollection)
132 {
133 RefPtr<Event> holder(Event::create());
134 ScriptValue holderWrapper = wrap(holder);
135
136 RefPtr<Property> p(Property::create(&document(), holder, "test"));
137
138 RefPtr<GCObservation> observation;
139 {
140 ScriptState::Scope scope(scriptState());
141 observation = GCObservation::create(p->promise(DOMWrapperWorld::mainWorl d()).v8Value());
142 }
143
144 gc();
145 EXPECT_FALSE(observation->wasCollected());
146
147 holderWrapper.clear();
148 gc();
149 EXPECT_TRUE(observation->wasCollected());
150
151 EXPECT_EQ(Property::Pending, p->state());
152 }
153
154 TEST_F(ScriptPromisePropertyTest, Resolve_ResolvesScriptPromise)
155 {
156 RefPtr<Property> p(newProperty());
157
158 ScriptPromise promise = p->promise(DOMWrapperWorld::mainWorld());
159 ScriptValue value;
160 size_t nResolveCalls = 0;
161
162 {
163 ScriptState::Scope scope(scriptState());
164 promise.then(stub(value, nResolveCalls), notReached());
165 }
166
167 RefPtr<Event> event(Event::create());
168 p->resolve(event.get());
169 EXPECT_EQ(Property::Resolved, p->state());
170
171 isolate()->RunMicrotasks();
172 EXPECT_EQ(1u, nResolveCalls);
173 EXPECT_EQ(wrap(event), value);
174 }
175
176 TEST_F(ScriptPromisePropertyTest, Reject_RejectsScriptPromise)
177 {
178 RefPtr<Property> p(newProperty());
179
180 RefPtr<Event> event(Event::create());
181 p->reject(event.get());
182 EXPECT_EQ(Property::Rejected, p->state());
183
184 ScriptValue value;
185 size_t nRejectCalls = 0;
186
187 {
188 ScriptState::Scope scope(scriptState());
189 p->promise(DOMWrapperWorld::mainWorld()).then(notReached(), stub(value, nRejectCalls));
190 }
191
192 isolate()->RunMicrotasks();
193 EXPECT_EQ(1u, nRejectCalls);
194 EXPECT_EQ(wrap(event), value);
195 }
196
197 TEST_F(ScriptPromisePropertyTest, Settle_IsIdempotent)
198 {
199 RefPtr<Property> p(newProperty());
200
201 RefPtr<Event> eventA(Event::create());
202 p->reject(eventA.get());
203 EXPECT_EQ(Property::Rejected, p->state());
204
205 RefPtr<Event> eventB(Event::create());
206 p->resolve(eventB.get());
207 EXPECT_EQ(Property::Rejected, p->state());
208
209 ScriptValue value;
210 size_t nRejectCalls = 0;
211
212 {
213 ScriptState::Scope scope(scriptState());
214 p->promise(DOMWrapperWorld::mainWorld()).then(notReached(), stub(value, nRejectCalls));
215 }
216
217 isolate()->RunMicrotasks();
218
219 EXPECT_EQ(1u, nRejectCalls);
220 EXPECT_EQ(wrap(eventA), value);
221
222 RefPtr<Event> eventC(Event::create());
223 p->reject(eventC.get());
224 EXPECT_EQ(1u, nRejectCalls);
225 }
226
227 TEST_F(ScriptPromisePropertyTest, Promise_DeadContext)
228 {
229 RefPtr<Property> p(newProperty());
230
231 RefPtr<Event> event(Event::create());
232 p->resolve(event.get());
233 EXPECT_EQ(Property::Resolved, p->state());
234
235 destroyContext();
236
237 EXPECT_TRUE(p->promise(DOMWrapperWorld::mainWorld()).isEmpty());
238 }
239
240 TEST_F(ScriptPromisePropertyTest, Resolve_DeadContext)
241 {
242 RefPtr<Property> p(newProperty());
243
244 {
245 ScriptState::Scope scope(scriptState());
246 p->promise(DOMWrapperWorld::mainWorld()).then(notReached(), notReached() );
247 }
248
249 destroyContext();
250
251 RefPtr<Event> event(Event::create());
252 p->resolve(event.get());
253 EXPECT_EQ(Property::Pending, p->state());
254
255 v8::Isolate::GetCurrent()->RunMicrotasks();
256 }
257
258 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698