promise.rb 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +9 -0
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -1
- data/config/reek.yml +4 -3
- data/config/rubocop.yml +4 -0
- data/lib/promise.rb +23 -47
- data/lib/promise/callback.rb +25 -33
- data/lib/promise/version.rb +1 -1
- data/spec/promise_spec.rb +20 -20
- metadata +2 -2
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# promise.rb changelog
|
2
2
|
|
3
|
+
## 0.6.0 (December 21, 2013)
|
4
|
+
|
5
|
+
* Most of Promise and Callback have been rewritten. Less code.
|
6
|
+
* The rejection reason isn't overloaded with the promise's backtrace anymore as
|
7
|
+
introduced in 0.5.0. Instead, Promise#backtrace will be populated with the
|
8
|
+
originating call to #fulfill or #reject.
|
9
|
+
* The backtrace no longer guarantees that the actual caller is its first
|
10
|
+
element (thank you JRuby).
|
11
|
+
|
3
12
|
## 0.5.0 (December 16, 2013)
|
4
13
|
|
5
14
|
* Fulfillment value and rejection reason are no longer being frozen
|
data/config/flay.yml
CHANGED
data/config/flog.yml
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
---
|
2
|
-
threshold:
|
2
|
+
threshold: 10.8
|
data/config/reek.yml
CHANGED
@@ -20,7 +20,8 @@ DuplicateMethodCall:
|
|
20
20
|
enabled: true
|
21
21
|
exclude: []
|
22
22
|
max_calls: 1
|
23
|
-
allow_calls:
|
23
|
+
allow_calls:
|
24
|
+
- source.backtrace
|
24
25
|
FeatureEnvy:
|
25
26
|
enabled: false
|
26
27
|
exclude: []
|
@@ -49,7 +50,7 @@ NilCheck:
|
|
49
50
|
RepeatedConditional:
|
50
51
|
enabled: true
|
51
52
|
exclude: []
|
52
|
-
max_ifs:
|
53
|
+
max_ifs: 3
|
53
54
|
TooManyInstanceVariables:
|
54
55
|
enabled: true
|
55
56
|
exclude: []
|
@@ -57,7 +58,7 @@ TooManyInstanceVariables:
|
|
57
58
|
TooManyMethods:
|
58
59
|
enabled: true
|
59
60
|
exclude: []
|
60
|
-
max_methods:
|
61
|
+
max_methods: 12
|
61
62
|
TooManyStatements:
|
62
63
|
enabled: true
|
63
64
|
exclude:
|
data/config/rubocop.yml
CHANGED
data/lib/promise.rb
CHANGED
@@ -8,12 +8,11 @@ require 'promise/progress'
|
|
8
8
|
class Promise
|
9
9
|
include Promise::Progress
|
10
10
|
|
11
|
-
attr_reader :value, :reason
|
11
|
+
attr_reader :state, :value, :reason, :backtrace
|
12
12
|
|
13
13
|
def initialize
|
14
14
|
@state = :pending
|
15
|
-
@
|
16
|
-
@on_reject = []
|
15
|
+
@callbacks = []
|
17
16
|
end
|
18
17
|
|
19
18
|
def pending?
|
@@ -30,77 +29,54 @@ class Promise
|
|
30
29
|
|
31
30
|
def then(on_fulfill = nil, on_reject = nil, &block)
|
32
31
|
on_fulfill ||= block
|
33
|
-
next_promise =
|
32
|
+
next_promise = Promise.new
|
34
33
|
|
35
|
-
|
34
|
+
add_callback { Callback.new(on_fulfill, on_reject, next_promise) }
|
36
35
|
next_promise
|
37
36
|
end
|
38
37
|
|
38
|
+
def add_callback(&generator)
|
39
|
+
if pending?
|
40
|
+
@callbacks << generator
|
41
|
+
else
|
42
|
+
dispatch!(generator.call)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
39
46
|
def sync
|
40
47
|
wait if pending?
|
41
|
-
|
48
|
+
raise reason if rejected?
|
42
49
|
value
|
43
50
|
end
|
44
51
|
|
45
|
-
def fulfill(value = nil)
|
46
|
-
dispatch(
|
52
|
+
def fulfill(value = nil, backtrace = nil)
|
53
|
+
dispatch(backtrace) do
|
47
54
|
@state = :fulfilled
|
48
55
|
@value = value
|
49
56
|
end
|
50
57
|
end
|
51
58
|
|
52
|
-
def reject(reason = nil)
|
53
|
-
|
54
|
-
dispatch(@on_reject, reason) do
|
59
|
+
def reject(reason = RuntimeError, backtrace = nil)
|
60
|
+
dispatch(backtrace) do
|
55
61
|
@state = :rejected
|
56
62
|
@reason = reason
|
57
63
|
end
|
58
64
|
end
|
59
65
|
|
60
|
-
|
61
|
-
|
62
|
-
def add_callbacks(on_fulfill, on_reject)
|
63
|
-
next_promise = self.class.new
|
64
|
-
@on_fulfill << FulfillCallback.new(on_fulfill, next_promise)
|
65
|
-
@on_reject << RejectCallback.new(on_reject, next_promise)
|
66
|
-
next_promise
|
67
|
-
end
|
68
|
-
|
69
|
-
def dispatch(callbacks, arg)
|
66
|
+
def dispatch(backtrace)
|
70
67
|
if pending?
|
71
68
|
yield
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
# Callback#assume_state uses #dispatch as returned_promise's on_fulfill
|
76
|
-
# and on_reject callback. Without an explicit return value, the implicit
|
77
|
-
# return value might be the callbacks array, and thus returned_promise
|
78
|
-
# would be fulfilled (or rejected) with that array. It would be frozen
|
79
|
-
# from then on, letting further calls to #then crash.
|
80
|
-
nil
|
81
|
-
end
|
82
|
-
|
83
|
-
def maybe_dispatch(fulfill_callback, reject_callback)
|
84
|
-
if fulfilled?
|
85
|
-
dispatch!(fulfill_callback, value)
|
86
|
-
end
|
87
|
-
|
88
|
-
if rejected?
|
89
|
-
dispatch!(reject_callback, reason)
|
69
|
+
@backtrace = backtrace || caller
|
70
|
+
@callbacks.each { |generator| dispatch!(generator.call) }
|
71
|
+
nil
|
90
72
|
end
|
91
73
|
end
|
92
74
|
|
93
|
-
def dispatch!(callback
|
94
|
-
defer { callback.dispatch(
|
75
|
+
def dispatch!(callback)
|
76
|
+
defer { callback.dispatch(self) }
|
95
77
|
end
|
96
78
|
|
97
79
|
def defer
|
98
80
|
yield
|
99
81
|
end
|
100
|
-
|
101
|
-
def build_reason(reason, backtrace)
|
102
|
-
reason = reason.new if reason.respond_to?(:new)
|
103
|
-
reason.set_backtrace(backtrace) unless reason.backtrace
|
104
|
-
reason
|
105
|
-
end
|
106
82
|
end
|
data/lib/promise/callback.rb
CHANGED
@@ -2,55 +2,47 @@
|
|
2
2
|
|
3
3
|
class Promise
|
4
4
|
class Callback
|
5
|
-
def initialize(
|
6
|
-
@
|
5
|
+
def initialize(on_fulfill, on_reject, next_promise)
|
6
|
+
@on_fulfill, @on_reject = on_fulfill, on_reject
|
7
7
|
@next_promise = next_promise
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
def block_for(promise)
|
11
|
+
promise.fulfilled? ? @on_fulfill : @on_reject
|
12
|
+
end
|
11
13
|
|
12
|
-
def
|
13
|
-
|
14
|
-
rescue => error
|
15
|
-
@next_promise.reject(error)
|
16
|
-
raise
|
14
|
+
def param_for(promise)
|
15
|
+
promise.fulfilled? ? promise.value : promise.reason
|
17
16
|
end
|
18
17
|
|
19
|
-
def
|
20
|
-
if
|
21
|
-
|
18
|
+
def dispatch(promise)
|
19
|
+
if (block = block_for(promise))
|
20
|
+
handle_result(promise) { execute(promise, block) }
|
22
21
|
else
|
23
|
-
@next_promise
|
22
|
+
assume_state(promise, @next_promise)
|
24
23
|
end
|
25
24
|
end
|
26
25
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
def execute(promise, block)
|
27
|
+
block.call(param_for(promise))
|
28
|
+
rescue => ex
|
29
|
+
@next_promise.reject(ex, promise.backtrace)
|
30
|
+
raise
|
32
31
|
end
|
33
|
-
end
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
result = execute(value)
|
39
|
-
handle_result(result)
|
33
|
+
def handle_result(promise)
|
34
|
+
if Promise === (result = yield)
|
35
|
+
assume_state(result, @next_promise)
|
40
36
|
else
|
41
|
-
|
37
|
+
@next_promise.fulfill(result, promise.backtrace)
|
42
38
|
end
|
43
39
|
end
|
44
|
-
end
|
45
40
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
else
|
52
|
-
@next_promise.reject(reason)
|
53
|
-
end
|
41
|
+
def assume_state(source, target)
|
42
|
+
on_fulfill = proc { target.fulfill(source.value, source.backtrace) }
|
43
|
+
on_reject = proc { target.reject(source.reason, source.backtrace) }
|
44
|
+
|
45
|
+
source.then(on_fulfill, on_reject)
|
54
46
|
end
|
55
47
|
end
|
56
48
|
end
|
data/lib/promise/version.rb
CHANGED
data/spec/promise_spec.rb
CHANGED
@@ -223,6 +223,7 @@ describe Promise do
|
|
223
223
|
|
224
224
|
expect(promise2).to be_fulfilled
|
225
225
|
expect(promise2.value).to eq(other_value)
|
226
|
+
expect(promise2.backtrace).to be(subject.backtrace)
|
226
227
|
end
|
227
228
|
|
228
229
|
it 'fulfills promise2 with value returned by on_reject' do
|
@@ -231,22 +232,25 @@ describe Promise do
|
|
231
232
|
|
232
233
|
expect(promise2).to be_fulfilled
|
233
234
|
expect(promise2.value).to eq(other_value)
|
235
|
+
expect(promise2.backtrace).to be(subject.backtrace)
|
234
236
|
end
|
235
237
|
|
236
238
|
it 'rejects promise2 with error raised by on_fulfill' do
|
237
|
-
promise2 = subject.then(proc { |_|
|
239
|
+
promise2 = subject.then(proc { |_| raise error })
|
238
240
|
expect { subject.fulfill(value) }.to raise_error(error)
|
239
241
|
|
240
242
|
expect(promise2).to be_rejected
|
241
243
|
expect(promise2.reason).to eq(error)
|
244
|
+
expect(promise2.backtrace).to be(subject.backtrace)
|
242
245
|
end
|
243
246
|
|
244
247
|
it 'rejects promise2 with error raised by on_reject' do
|
245
|
-
promise2 = subject.then(nil, proc { |_|
|
248
|
+
promise2 = subject.then(nil, proc { |_| raise error })
|
246
249
|
expect { subject.reject(reason) }.to raise_error(error)
|
247
250
|
|
248
251
|
expect(promise2).to be_rejected
|
249
252
|
expect(promise2.reason).to eq(error)
|
253
|
+
expect(promise2.backtrace).to be(subject.backtrace)
|
250
254
|
end
|
251
255
|
|
252
256
|
describe 'on_fulfill returns promise' do
|
@@ -259,6 +263,7 @@ describe Promise do
|
|
259
263
|
returned_promise.fulfill(other_value)
|
260
264
|
expect(promise2).to be_fulfilled
|
261
265
|
expect(promise2.value).to eq(other_value)
|
266
|
+
expect(promise2.backtrace).to be(returned_promise.backtrace)
|
262
267
|
end
|
263
268
|
|
264
269
|
it 'makes promise2 assume rejected state of returned promise' do
|
@@ -270,6 +275,7 @@ describe Promise do
|
|
270
275
|
returned_promise.reject(other_reason)
|
271
276
|
expect(promise2).to be_rejected
|
272
277
|
expect(promise2.reason).to eq(other_reason)
|
278
|
+
expect(promise2.backtrace).to be(returned_promise.backtrace)
|
273
279
|
end
|
274
280
|
end
|
275
281
|
|
@@ -283,6 +289,7 @@ describe Promise do
|
|
283
289
|
returned_promise.fulfill(other_value)
|
284
290
|
expect(promise2).to be_fulfilled
|
285
291
|
expect(promise2.value).to eq(other_value)
|
292
|
+
expect(promise2.backtrace).to be(returned_promise.backtrace)
|
286
293
|
end
|
287
294
|
|
288
295
|
it 'makes promise2 assume rejected state of returned promise' do
|
@@ -294,6 +301,7 @@ describe Promise do
|
|
294
301
|
returned_promise.reject(other_reason)
|
295
302
|
expect(promise2).to be_rejected
|
296
303
|
expect(promise2.reason).to eq(other_reason)
|
304
|
+
expect(promise2.backtrace).to be(returned_promise.backtrace)
|
297
305
|
end
|
298
306
|
end
|
299
307
|
|
@@ -304,6 +312,7 @@ describe Promise do
|
|
304
312
|
|
305
313
|
expect(promise2).to be_fulfilled
|
306
314
|
expect(promise2.value).to eq(value)
|
315
|
+
expect(promise2.backtrace).to be(subject.backtrace)
|
307
316
|
end
|
308
317
|
end
|
309
318
|
|
@@ -314,6 +323,7 @@ describe Promise do
|
|
314
323
|
|
315
324
|
expect(promise2).to be_rejected
|
316
325
|
expect(promise2.reason).to eq(reason)
|
326
|
+
expect(promise2.backtrace).to be(subject.backtrace)
|
317
327
|
end
|
318
328
|
end
|
319
329
|
end
|
@@ -355,6 +365,12 @@ describe Promise do
|
|
355
365
|
subject.fulfill
|
356
366
|
expect(subject.value).to be(nil)
|
357
367
|
end
|
368
|
+
|
369
|
+
it 'sets the backtrace' do
|
370
|
+
subject.fulfill
|
371
|
+
expect(subject.backtrace.join)
|
372
|
+
.to include(__FILE__ + ':' + (__LINE__ - 2).to_s)
|
373
|
+
end
|
358
374
|
end
|
359
375
|
|
360
376
|
describe '#reject' do
|
@@ -364,30 +380,14 @@ describe Promise do
|
|
364
380
|
|
365
381
|
it 'does not require a reason' do
|
366
382
|
subject.reject
|
367
|
-
expect(subject.reason).to
|
368
|
-
end
|
369
|
-
|
370
|
-
it 'allows nil reason' do
|
371
|
-
subject.reject(nil)
|
372
|
-
expect(subject.reason).to be_a(RuntimeError)
|
383
|
+
expect(subject.reason).to be(RuntimeError)
|
373
384
|
end
|
374
385
|
|
375
386
|
it 'sets the backtrace' do
|
376
387
|
subject.reject
|
377
|
-
expect(subject.
|
388
|
+
expect(subject.backtrace.join)
|
378
389
|
.to include(__FILE__ + ':' + (__LINE__ - 2).to_s)
|
379
390
|
end
|
380
|
-
|
381
|
-
it 'does not override backtrace' do
|
382
|
-
subject.reject(reason)
|
383
|
-
expect(subject.reason.backtrace).to be(backtrace)
|
384
|
-
end
|
385
|
-
|
386
|
-
it 'builds exception object for custom error class' do
|
387
|
-
cls = Class.new(StandardError)
|
388
|
-
subject.reject(cls)
|
389
|
-
expect(subject.reason).to be_a(cls)
|
390
|
-
end
|
391
391
|
end
|
392
392
|
|
393
393
|
describe '#sync' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: promise.rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-12-
|
12
|
+
date: 2013-12-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|