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

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: More feedback. Keeping separate header file for now. 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
93 // of events, and 'Ready' because it is an available property name
94 // that won't bloat V8HiddenValue with a test property name.
95
96 ScriptValue wrap(PassRefPtr<Event> event)
97 {
98 ScriptState::Scope scope(scriptState());
99 return ScriptValue(scriptState(), V8ValueTraits<Event>::toV8Value(event, scriptState()->context()->Global(), isolate()));
100 }
101
102 typedef ScriptPromiseProperty<RefPtr<Event>, Event*, Event*> Property;
103 PassRefPtr<Property> newProperty() { return Property::create(&document(), Ev ent::create(), Property::Ready); }
104
105 private:
106 OwnPtr<DummyPageHolder> m_page;
107 };
108
109 TEST_F(ScriptPromisePropertyTest, Promise_IsStableObject)
110 {
111 RefPtr<Property> p(newProperty());
112 ScriptPromise v = p->promise(DOMWrapperWorld::mainWorld());
113 ScriptPromise w = p->promise(DOMWrapperWorld::mainWorld());
114 EXPECT_EQ(v, w);
115 EXPECT_FALSE(v.isEmpty());
116 EXPECT_EQ(Property::Pending, p->state());
117 }
118
119 TEST_F(ScriptPromisePropertyTest, Promise_IsStableObjectAfterSettling)
120 {
121 RefPtr<Property> p(newProperty());
122 ScriptPromise v = p->promise(DOMWrapperWorld::mainWorld());
123
124 RefPtr<Event> value(Event::create());
125 p->resolve(value.get());
126 EXPECT_EQ(Property::Resolved, p->state());
127
128 ScriptPromise w = p->promise(DOMWrapperWorld::mainWorld());
129 EXPECT_EQ(v, w);
130 EXPECT_FALSE(v.isEmpty());
131 }
132
133 TEST_F(ScriptPromisePropertyTest, Promise_DoesNotImpedeGarbageCollection)
134 {
135 RefPtr<Event> holder(Event::create());
136 ScriptValue holderWrapper = wrap(holder);
137
138 RefPtr<Property> p(Property::create(&document(), holder, Property::Ready));
139
140 RefPtr<GCObservation> observation;
141 {
142 ScriptState::Scope scope(scriptState());
143 observation = GCObservation::create(p->promise(DOMWrapperWorld::mainWorl d()).v8Value());
144 }
145
146 gc();
147 EXPECT_FALSE(observation->wasCollected());
148
149 holderWrapper.clear();
150 gc();
151 EXPECT_TRUE(observation->wasCollected());
152
153 EXPECT_EQ(Property::Pending, p->state());
154 }
155
156 TEST_F(ScriptPromisePropertyTest, Resolve_ResolvesScriptPromise)
157 {
158 RefPtr<Property> p(newProperty());
159
160 ScriptPromise promise = p->promise(DOMWrapperWorld::mainWorld());
161 ScriptValue value;
162 size_t nResolveCalls = 0;
163
164 {
165 ScriptState::Scope scope(scriptState());
166 promise.then(stub(value, nResolveCalls), notReached());
167 }
168
169 RefPtr<Event> event(Event::create());
170 p->resolve(event.get());
171 EXPECT_EQ(Property::Resolved, p->state());
172
173 isolate()->RunMicrotasks();
174 EXPECT_EQ(1u, nResolveCalls);
175 EXPECT_EQ(wrap(event), value);
176 }
177
178 TEST_F(ScriptPromisePropertyTest, Reject_RejectsScriptPromise)
179 {
180 RefPtr<Property> p(newProperty());
181
182 RefPtr<Event> event(Event::create());
183 p->reject(event.get());
184 EXPECT_EQ(Property::Rejected, p->state());
185
186 ScriptValue value;
187 size_t nRejectCalls = 0;
188
189 {
190 ScriptState::Scope scope(scriptState());
191 p->promise(DOMWrapperWorld::mainWorld()).then(notReached(), stub(value, nRejectCalls));
192 }
193
194 isolate()->RunMicrotasks();
195 EXPECT_EQ(1u, nRejectCalls);
196 EXPECT_EQ(wrap(event), value);
197 }
198
199 TEST_F(ScriptPromisePropertyTest, Promise_DeadContext)
200 {
201 RefPtr<Property> p(newProperty());
202
203 RefPtr<Event> event(Event::create());
204 p->resolve(event.get());
205 EXPECT_EQ(Property::Resolved, p->state());
206
207 destroyContext();
208
209 EXPECT_TRUE(p->promise(DOMWrapperWorld::mainWorld()).isEmpty());
210 }
211
212 TEST_F(ScriptPromisePropertyTest, Resolve_DeadContext)
213 {
214 RefPtr<Property> p(newProperty());
215
216 {
217 ScriptState::Scope scope(scriptState());
218 p->promise(DOMWrapperWorld::mainWorld()).then(notReached(), notReached() );
219 }
220
221 destroyContext();
222
223 RefPtr<Event> event(Event::create());
224 p->resolve(event.get());
225 EXPECT_EQ(Property::Pending, p->state());
226
227 v8::Isolate::GetCurrent()->RunMicrotasks();
228 }
229
230 } // namespace
OLDNEW
« no previous file with comments | « Source/bindings/core/v8/ScriptPromisePropertyBase.cpp ('k') | Source/bindings/core/v8/V8HiddenValue.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698