volt 0.9.5.pre3 → 0.9.5.pre4

Sign up to get free protection for your applications and to get access to all the features.
@@ -168,43 +168,23 @@ module Volt
168
168
  end
169
169
 
170
170
  # Call a method on the model once the model is loaded. Return a promise
171
- # that will resolve the result of the method, or reject with any
172
- # Exceptions.
173
- def run_once_loaded(block)
171
+ # that will resolve when the model is loaded
172
+ def run_once_loaded
174
173
  promise = Promise.new
175
174
 
176
- # call once the method is loaded.
177
- model_loaded = proc do
178
- begin
179
- result = yield
180
- promise.resolve(result)
181
- rescue Exception => error
182
- promise.reject(error)
183
- end
184
- end
185
-
186
- # Run the block after resolve if a block is passed in
187
- if block
188
- promise2 = promise.then do |val|
189
- block.call(val)
190
- end
191
- else
192
- promise2 = promise
193
- end
194
-
195
175
  if @model.loaded_state == :loaded
196
- model_loaded.call
176
+ promise.resolve(nil)
197
177
  else
198
178
  proc do |comp|
199
179
  if @model.loaded_state == :loaded
200
- model_loaded.call
180
+ promise.resolve(nil)
201
181
 
202
182
  comp.stop
203
183
  end
204
184
  end.watch!
205
185
  end
206
186
 
207
- promise2
187
+ promise
208
188
  end
209
189
 
210
190
  # Returns a promise that is resolved/rejected when the query is complete. Any
@@ -25,7 +25,6 @@ module Volt
25
25
  super
26
26
  end
27
27
 
28
- # puts "GOT: #{res.inspect}"
29
28
  res
30
29
  end
31
30
 
@@ -11,13 +11,16 @@ module Volt
11
11
  @old_size = 0
12
12
  end
13
13
 
14
+ def respond_to_missing?(method_name, include_private = false)
15
+ @array.respond_to?(method_name, include_private) || super
16
+ end
17
+
14
18
  # Forward any missing methods to the array
15
19
  def method_missing(method_name, *args, &block)
16
20
  # Long term we should probably handle all Enum methods
17
21
  # directly for smarter updating. For now, just depend on size
18
22
  # so updates retrigger the whole method call.
19
23
  @size_dep.depend
20
-
21
24
  @array.send(method_name, *args, &block)
22
25
  end
23
26
 
@@ -77,7 +77,7 @@ module Volt
77
77
  connect_to_peers
78
78
  end
79
79
  else
80
- Volt.logger.error('Unable to connect to the database. Volt will still run, but the message bus requires a database connection to setup connections between nodes, so the message bus has been disabled. This means updates will not be propagated between instances (server, console, runners, etc...)')
80
+ Volt.logger.error('Unable to connect to the database. Currently Volt requires running mongodb for a few things to work. Volt will still run, but the message bus requires a database connection to setup connections between nodes, so the message bus has been disabled. Also, the store collection can not be used without a database. This means updates will not be propagated between instances (server, console, runners, etc...)')
81
81
  end
82
82
  end
83
83
 
@@ -181,7 +181,7 @@ module Volt
181
181
  def still_alive?(peer_server_id)
182
182
  # Unable to write to the socket, retry until the instance is no
183
183
  # longer marking its self as active in the database
184
- peer_table = @volt_app.store._active_volt_instances
184
+ peer_table = @volt_app.store.active_volt_instances
185
185
  peer = peer_table.where(server_id: peer_server_id).first.sync
186
186
  if peer
187
187
  # Found the peer, retry if it has reported in in the last 2
@@ -33,7 +33,7 @@ module Volt
33
33
 
34
34
  # Register this server as active with the database
35
35
  def register
36
- instances = @volt_app.store._active_volt_instances
36
+ instances = @volt_app.store.active_volt_instances
37
37
  instances.where(server_id: @server_id).first.then do |item|
38
38
  ips = local_ips.join(',')
39
39
  time = Time.now.to_i
@@ -50,10 +50,11 @@ module Volt
50
50
 
51
51
  rack_app.use HttpResource, volt_app, volt_app.router
52
52
 
53
+ # serve assets from public
53
54
  rack_app.use Rack::Static,
54
55
  urls: ['/'],
55
- root: 'config/base',
56
- index: '',
56
+ root: 'public',
57
+ index: 'index.html',
57
58
  header_rules: [
58
59
  [:all, { 'Cache-Control' => 'public, max-age=86400' }]
59
60
  ]
@@ -4,6 +4,16 @@ require 'uri'
4
4
  # from the dependencies.rb files.
5
5
  module Volt
6
6
  class AssetFiles
7
+ def self.from_cache(component_name, component_paths)
8
+ # @cache ||= {}
9
+
10
+ # @cache[component_name] ||= begin
11
+ # not cached, create
12
+
13
+ self.new(component_name, component_paths)
14
+ # end
15
+ end
16
+
7
17
  def initialize(component_name, component_paths)
8
18
  @component_paths = component_paths
9
19
  @assets = []
@@ -61,6 +71,14 @@ module Volt
61
71
  end
62
72
  end
63
73
 
74
+ # Called when you want to add a gem to the opal load path so it can be
75
+ # required on the client side.
76
+ def opal_gem(gem_name)
77
+ Opal.use_gem(gem_name)
78
+ Opal.paths.uniq!
79
+ # require(gem_name)
80
+ end
81
+
64
82
  def components
65
83
  @included_components.keys
66
84
  end
@@ -17,7 +17,7 @@ module Volt
17
17
  # Start with config code
18
18
  code = @client ? generate_config_code : ''
19
19
 
20
- asset_files = AssetFiles.new(@component_name, @component_paths)
20
+ asset_files = AssetFiles.from_cache(@component_name, @component_paths)
21
21
  asset_files.component_paths.each do |component_path, component_name|
22
22
  code << ComponentTemplates.new(component_path, component_name, @client).code
23
23
  code << "\n\n"
@@ -58,11 +58,11 @@ module Volt
58
58
 
59
59
  def javascript_tags
60
60
  # TODO: Cache somehow, this is being loaded every time
61
- AssetFiles.new('main', @component_paths).javascript_tags(@volt_app)
61
+ AssetFiles.from_cache('main', @component_paths).javascript_tags(@volt_app)
62
62
  end
63
63
 
64
64
  def css_tags
65
- AssetFiles.new('main', @component_paths).css_tags
65
+ AssetFiles.from_cache('main', @component_paths).css_tags
66
66
  end
67
67
  end
68
68
  end
@@ -72,6 +72,9 @@ module Volt
72
72
  run environment
73
73
  end
74
74
 
75
+ # Remove dup paths
76
+ Opal.paths.uniq!
77
+
75
78
  @environment.logger.level ||= Logger::DEBUG
76
79
  source_map_enabled = Volt.source_maps?
77
80
  if source_map_enabled
@@ -29,8 +29,6 @@ module Volt
29
29
  RSpec.configuration.filter_run_excluding type: :feature
30
30
  end
31
31
 
32
-
33
-
34
32
  cleanup_db = -> do
35
33
  volt_app.database.drop_database
36
34
 
@@ -1,6 +1,3 @@
1
- # Require the original promise library first.
2
- require 'volt/utils/promise'
3
-
4
1
  # A temp patch for promises until https://github.com/opal/opal/pull/725 is released.
5
2
  class Promise
6
3
  class UnrealizedPromiseException < RuntimeError ; end
@@ -113,6 +110,10 @@ class Promise
113
110
  end
114
111
 
115
112
  if error
113
+ if error.is_a?(RSpec::Expectations::ExpectationNotMetError)
114
+ # re-raise
115
+ raise error
116
+ end
116
117
  err_str = "Exception in Promise at .sync: #{error.inspect}"
117
118
  err_str += error.backtrace.join("\n") if error.respond_to?(:backtrace)
118
119
  Volt.logger.error(err_str)
data/lib/volt/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Volt
2
2
  module Version
3
- STRING = '0.9.5.pre3'
3
+ STRING = '0.9.5.pre4'
4
4
  end
5
5
  end
data/lib/volt/volt/app.rb CHANGED
@@ -88,6 +88,11 @@ module Volt
88
88
 
89
89
  load_app_code
90
90
 
91
+ # Load up the main component dependencies. This is needed to load in
92
+ # any opal_gem calls in dependencies.rb
93
+ # TODO: Needs to support all components
94
+ AssetFiles.from_cache('main', component_paths)
95
+
91
96
  reset_query_pool!
92
97
 
93
98
  # Setup the middleware that we can only setup after all components boot.
@@ -93,12 +93,12 @@ module Volt
93
93
 
94
94
  # Put in a deprecation placeholder
95
95
  def user
96
- Volt.logger.warn('deprication: Volt.user has been renamed to Volt.current_user (to be more clear about what it returns). Volt.user will be deprecated in the future.')
96
+ Volt.logger.warn('Deprecation: Volt.user has been renamed to Volt.current_user (to be more clear about what it returns). Volt.user will be deprecated in the future.')
97
97
  current_user
98
98
  end
99
99
 
100
100
  def fetch_current_user
101
- Volt.logger.warn("Deprication Warning: fetch current user have been depricated, Volt.current_user returns a promise now.")
101
+ Volt.logger.warn("Deprecation Warning: fetch current user have been depricated, Volt.current_user returns a promise now.")
102
102
  current_user
103
103
  end
104
104
 
@@ -3,6 +3,7 @@ require 'volt/extra_core/array'
3
3
 
4
4
  class TestClassAttributes
5
5
  class_attribute :some_data
6
+ class_attribute :attr2
6
7
  end
7
8
 
8
9
  class TestSubClassAttributes < TestClassAttributes
@@ -30,4 +31,14 @@ describe 'extra_core class addons' do
30
31
  expect(TestSubClassAttributes.some_data).to eq(10)
31
32
  expect(TestSubClassAttributes2.some_data).to eq(15)
32
33
  end
34
+
35
+ it 'should let you change a class attribute on the child without affecting the parent' do
36
+ TestClassAttributes.attr2 = 1
37
+ expect(TestSubClassAttributes.attr2).to eq(1)
38
+
39
+ TestSubClassAttributes.attr2 = 2
40
+ expect(TestClassAttributes.attr2).to eq(1)
41
+ expect(TestSubClassAttributes.attr2).to eq(2)
42
+ expect(TestSubClassAttributes2.attr2).to eq(1)
43
+ end
33
44
  end
@@ -3,7 +3,6 @@ require 'spec_helper'
3
3
  describe 'bindings test', type: :feature, sauce: true do
4
4
  it 'should load the page' do
5
5
  visit '/'
6
- sleep 10
7
6
 
8
7
  expect(page).to have_content('Kitchen Sink')
9
8
  end
@@ -21,4 +21,20 @@ describe Volt::ArrayModel do
21
21
  Volt::Computation.flush!
22
22
  expect(count).to eq(2)
23
23
  end
24
+
25
+ it 'should return the index of a model' do
26
+ array_model = Volt::ArrayModel.new([1,2,3])
27
+
28
+ expect(array_model.index(2)).to eq(1)
29
+ end
30
+
31
+ it 'should flatten' do
32
+ array = Volt::ArrayModel.new([])
33
+
34
+ array << Volt::ArrayModel.new([Volt::ArrayModel.new([1,2]), Volt::ArrayModel.new([3])])
35
+ array << Volt::ArrayModel.new([Volt::ArrayModel.new([4,5]), Volt::ArrayModel.new([6])])
36
+
37
+ expect(array.flatten.size).to eq(6)
38
+ expect(array.to_a.flatten.size).to eq(6)
39
+ end
24
40
  end
@@ -6,6 +6,9 @@ class ExampleModelWithField < Volt::Model
6
6
  field :value, Numeric
7
7
  end
8
8
 
9
+ class ExampleModelWithField2 < ExampleModelWithField
10
+ end
11
+
9
12
  describe 'field helpers' do
10
13
  let(:model) { ExampleModelWithField.new }
11
14
  it 'should allow a user to setup a field that can be written to and read' do
@@ -23,7 +26,7 @@ describe 'field helpers' do
23
26
 
24
27
  it 'should raise an error when an invalid cast type is provided' do
25
28
  expect do
26
- ExampleModelWithField.field :awesome, Array
29
+ ExampleModelWithField2.field :awesome, Array
27
30
  end.to raise_error(FieldHelpers::InvalidFieldClass)
28
31
  end
29
32
 
@@ -42,4 +45,8 @@ describe 'field helpers' do
42
45
  expect(error).to eq({})
43
46
  end
44
47
  end
48
+
49
+ it 'should track the fields on the model class' do
50
+ expect(ExampleModelWithField.fields_data).to eq({:name=>[nil, {}], :value=>[Numeric, {}]})
51
+ end
45
52
  end
@@ -46,6 +46,17 @@ class ::TestUpdateReadCheck < Volt::Model
46
46
  end
47
47
  end
48
48
 
49
+ class ::TestPromisePermission < Volt::Model
50
+ attr_reader :called_deny
51
+ permissions(:create) do
52
+ $test_promise = Promise.new
53
+ $test_promise.then do
54
+ @called_deny = true
55
+ deny
56
+ end
57
+ end
58
+ end
59
+
49
60
  describe 'model permissions' do
50
61
  let(:user_todo) { TestUserTodo.new }
51
62
 
@@ -162,5 +173,19 @@ describe 'model permissions' do
162
173
 
163
174
  expect(model.read_check).to eq(nil)
164
175
  end
176
+
177
+ it 'should allow permission blocks to return a promise' do
178
+ promise = store._test_promise_permissions.create({})
179
+
180
+ expect(promise.resolved?).to eq(false)
181
+ expect(promise.rejected?).to eq(false)
182
+ $test_promise.resolve(nil)
183
+
184
+ expect(promise.resolved?).to eq(false)
185
+ expect(promise.rejected?).to eq(true)
186
+ # puts "#{promise.error.inspect}"
187
+ # puts promise.error.backtrace.join("\n")
188
+ expect(promise.error.to_s).to match(/permissions did not allow create for/)
189
+ end
165
190
  end
166
191
  end
data/volt.gemspec CHANGED
@@ -44,7 +44,7 @@ Gem::Specification.new do |spec|
44
44
  spec.add_development_dependency 'capybara', '~> 2.4.2'
45
45
 
46
46
  # There is a big performance issue with selenium-webdriver on v2.45.0
47
- spec.add_development_dependency 'selenium-webdriver', '~> 2.43.0'
47
+ spec.add_development_dependency 'selenium-webdriver', '~> 2.46.2'
48
48
  spec.add_development_dependency 'chromedriver2-helper', '~> 0.0.8'
49
49
  spec.add_development_dependency 'poltergeist', '~> 1.5.0'
50
50
  spec.add_development_dependency 'thin', '~> 1.6.3'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: volt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.5.pre3
4
+ version: 0.9.5.pre4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Stout
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-24 00:00:00.000000000 Z
11
+ date: 2015-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -212,14 +212,14 @@ dependencies:
212
212
  requirements:
213
213
  - - "~>"
214
214
  - !ruby/object:Gem::Version
215
- version: 2.43.0
215
+ version: 2.46.2
216
216
  type: :development
217
217
  prerelease: false
218
218
  version_requirements: !ruby/object:Gem::Requirement
219
219
  requirements:
220
220
  - - "~>"
221
221
  - !ruby/object:Gem::Version
222
- version: 2.43.0
222
+ version: 2.46.2
223
223
  - !ruby/object:Gem::Dependency
224
224
  name: chromedriver2-helper
225
225
  requirement: !ruby/object:Gem::Requirement
@@ -374,6 +374,7 @@ files:
374
374
  - app/volt/assets/js/volt_watch.js
375
375
  - app/volt/config/dependencies.rb
376
376
  - app/volt/controllers/notices_controller.rb
377
+ - app/volt/models/active_volt_instance.rb
377
378
  - app/volt/models/user.rb
378
379
  - app/volt/tasks/live_query/live_query.rb
379
380
  - app/volt/tasks/live_query/live_query_pool.rb
@@ -572,7 +573,6 @@ files:
572
573
  - lib/volt/utils/logging/task_logger.rb
573
574
  - lib/volt/utils/modes.rb
574
575
  - lib/volt/utils/parsing.rb
575
- - lib/volt/utils/promise.rb
576
576
  - lib/volt/utils/promise_extensions.rb
577
577
  - lib/volt/utils/read_write_lock.rb
578
578
  - lib/volt/utils/set_patch.rb
@@ -1,429 +0,0 @@
1
- # A copy of the opal 0.8 promise library. The one in 0.7.x has some bugs.
2
-
3
- # {Promise} is used to help structure asynchronous code.
4
- #
5
- # It is available in the Opal standard library, and can be required in any Opal
6
- # application:
7
- #
8
- # require 'promise'
9
- #
10
- # ## Basic Usage
11
- #
12
- # Promises are created and returned as objects with the assumption that they
13
- # will eventually be resolved or rejected, but never both. A {Promise} has
14
- # a {#then} and {#fail} method (or one of their aliases) that can be used to
15
- # register a block that gets called once resolved or rejected.
16
- #
17
- # promise = Promise.new
18
- #
19
- # promise.then {
20
- # puts "resolved!"
21
- # }.fail {
22
- # puts "rejected!"
23
- # }
24
- #
25
- # # some time later
26
- # promise.resolve
27
- #
28
- # # => "resolved!"
29
- #
30
- # It is important to remember that a promise can only be resolved or rejected
31
- # once, so the block will only ever be called once (or not at all).
32
- #
33
- # ## Resolving Promises
34
- #
35
- # To resolve a promise, means to inform the {Promise} that it has succeeded
36
- # or evaluated to a useful value. {#resolve} can be passed a value which is
37
- # then passed into the block handler:
38
- #
39
- # def get_json
40
- # promise = Promise.new
41
- #
42
- # HTTP.get("some_url") do |req|
43
- # promise.resolve req.json
44
- # end
45
- #
46
- # promise
47
- # end
48
- #
49
- # get_json.then do |json|
50
- # puts "got some JSON from server"
51
- # end
52
- #
53
- # ## Rejecting Promises
54
- #
55
- # Promises are also designed to handle error cases, or situations where an
56
- # outcome is not as expected. Taking the previous example, we can also pass
57
- # a value to a {#reject} call, which passes that object to the registered
58
- # {#fail} handler:
59
- #
60
- # def get_json
61
- # promise = Promise.new
62
- #
63
- # HTTP.get("some_url") do |req|
64
- # if req.ok?
65
- # promise.resolve req.json
66
- # else
67
- # promise.reject req
68
- # end
69
- #
70
- # promise
71
- # end
72
- #
73
- # get_json.then {
74
- # # ...
75
- # }.fail { |req|
76
- # puts "it went wrong: #{req.message}"
77
- # }
78
- #
79
- # ## Chaining Promises
80
- #
81
- # Promises become even more useful when chained together. Each {#then} or
82
- # {#fail} call returns a new {Promise} which can be used to chain more and more
83
- # handlers together.
84
- #
85
- # promise.then { wait_for_something }.then { do_something_else }
86
- #
87
- # Rejections are propagated through the entire chain, so a "catch all" handler
88
- # can be attached at the end of the tail:
89
- #
90
- # promise.then { ... }.then { ... }.fail { ... }
91
- #
92
- # ## Composing Promises
93
- #
94
- # {Promise.when} can be used to wait for more than one promise to resolve (or
95
- # reject). Using the previous example, we could request two different json
96
- # requests and wait for both to finish:
97
- #
98
- # Promise.when(get_json, get_json2).then |first, second|
99
- # puts "got two json payloads: #{first}, #{second}"
100
- # end
101
- #
102
- class Promise
103
- def self.value(value)
104
- new.resolve(value)
105
- end
106
-
107
- def self.error(value)
108
- new.reject(value)
109
- end
110
-
111
- def self.when(*promises)
112
- When.new(promises)
113
- end
114
-
115
- attr_reader :error, :prev, :next
116
-
117
- def initialize(action = {})
118
- @action = action
119
-
120
- @realized = false
121
- @exception = false
122
- @value = nil
123
- @error = nil
124
- @delayed = false
125
-
126
- @prev = nil
127
- @next = nil
128
- end
129
-
130
- def value
131
- if Promise === @value
132
- @value.value
133
- else
134
- @value
135
- end
136
- end
137
-
138
- def act?
139
- @action.has_key?(:success) || @action.has_key?(:always)
140
- end
141
-
142
- def action
143
- @action.keys
144
- end
145
-
146
- def exception?
147
- @exception
148
- end
149
-
150
- def realized?
151
- !!@realized
152
- end
153
-
154
- def resolved?
155
- @realized == :resolve
156
- end
157
-
158
- def rejected?
159
- @realized == :reject
160
- end
161
-
162
- def ^(promise)
163
- promise << self
164
- self >> promise
165
-
166
- promise
167
- end
168
-
169
- def <<(promise)
170
- @prev = promise
171
-
172
- self
173
- end
174
-
175
- def >>(promise)
176
- @next = promise
177
-
178
- if exception?
179
- promise.reject(@delayed[0])
180
- elsif resolved?
181
- promise.resolve(@delayed ? @delayed[0] : value)
182
- elsif rejected?
183
- if !@action.has_key?(:failure) || Promise === (@delayed ? @delayed[0] : @error)
184
- promise.reject(@delayed ? @delayed[0] : error)
185
- elsif promise.action.include?(:always)
186
- promise.reject(@delayed ? @delayed[0] : error)
187
- end
188
- end
189
-
190
- self
191
- end
192
-
193
- def resolve(value = nil)
194
- if realized?
195
- raise ArgumentError, 'the promise has already been realized'
196
- end
197
-
198
- if Promise === value
199
- return (value << @prev) ^ self
200
- end
201
-
202
- begin
203
- if block = @action[:success] || @action[:always]
204
- value = block.call(value)
205
- end
206
-
207
- resolve!(value)
208
- rescue Exception => e
209
- exception!(e)
210
- end
211
-
212
- self
213
- end
214
-
215
- def resolve!(value)
216
- @realized = :resolve
217
- @value = value
218
-
219
- if @next
220
- @next.resolve(value)
221
- else
222
- @delayed = [value]
223
- end
224
- end
225
-
226
- def reject(value = nil)
227
- if realized?
228
- raise ArgumentError, 'the promise has already been realized'
229
- end
230
-
231
- if Promise === value
232
- return (value << @prev) ^ self
233
- end
234
-
235
- begin
236
- if block = @action[:failure] || @action[:always]
237
- value = block.call(value)
238
- end
239
-
240
- if @action.has_key?(:always)
241
- resolve!(value)
242
- else
243
- reject!(value)
244
- end
245
- rescue Exception => e
246
- exception!(e)
247
- end
248
-
249
- self
250
- end
251
-
252
- def reject!(value)
253
- @realized = :reject
254
- @error = value
255
-
256
- if @next
257
- @next.reject(value)
258
- else
259
- @delayed = [value]
260
- end
261
- end
262
-
263
- def exception!(error)
264
- @exception = true
265
-
266
- reject!(error)
267
- end
268
-
269
- def then(&block)
270
- if @next
271
- raise ArgumentError, 'a promise has already been chained'
272
- end
273
-
274
- self ^ Promise.new(success: block)
275
- end
276
-
277
- alias do then
278
-
279
- def fail(&block)
280
- if @next
281
- raise ArgumentError, 'a promise has already been chained'
282
- end
283
-
284
- self ^ Promise.new(failure: block)
285
- end
286
-
287
- alias rescue fail
288
- alias catch fail
289
-
290
- def always(&block)
291
- if @next
292
- raise ArgumentError, 'a promise has already been chained'
293
- end
294
-
295
- self ^ Promise.new(always: block)
296
- end
297
-
298
- alias finally always
299
- alias ensure always
300
-
301
- def trace(depth = nil, &block)
302
- if @next
303
- raise ArgumentError, 'a promise has already been chained'
304
- end
305
-
306
- self ^ Trace.new(depth, block)
307
- end
308
-
309
- def inspect
310
- result = "#<#{self.class}(#{object_id})"
311
-
312
- if @next
313
- result += " >> #{@next.inspect}"
314
- end
315
-
316
- if realized?
317
- result += ": #{(@value || @error).inspect}>"
318
- else
319
- result += ">"
320
- end
321
-
322
- result
323
- end
324
-
325
- class Trace < self
326
- def self.it(promise)
327
- current = []
328
-
329
- if promise.act? || promise.prev.nil?
330
- current.push(promise.value)
331
- end
332
-
333
- if prev = promise.prev
334
- current.concat(it(prev))
335
- else
336
- current
337
- end
338
- end
339
-
340
- def initialize(depth, block)
341
- @depth = depth
342
-
343
- super success: -> {
344
- trace = Trace.it(self).reverse
345
- trace.pop
346
-
347
- if depth && depth <= trace.length
348
- trace.shift(trace.length - depth)
349
- end
350
-
351
- block.call(*trace)
352
- }
353
- end
354
- end
355
-
356
- class When < self
357
- def initialize(promises = [])
358
- super()
359
-
360
- @wait = []
361
-
362
- promises.each {|promise|
363
- wait promise
364
- }
365
- end
366
-
367
- def each(&block)
368
- raise ArgumentError, 'no block given' unless block
369
-
370
- self.then {|values|
371
- values.each(&block)
372
- }
373
- end
374
-
375
- def collect(&block)
376
- raise ArgumentError, 'no block given' unless block
377
-
378
- self.then {|values|
379
- When.new(values.map(&block))
380
- }
381
- end
382
-
383
- def inject(*args, &block)
384
- self.then {|values|
385
- values.reduce(*args, &block)
386
- }
387
- end
388
-
389
- alias map collect
390
-
391
- alias reduce inject
392
-
393
- def wait(promise)
394
- unless Promise === promise
395
- promise = Promise.value(promise)
396
- end
397
-
398
- if promise.act?
399
- promise = promise.then
400
- end
401
-
402
- @wait << promise
403
-
404
- promise.always {
405
- try if @next
406
- }
407
-
408
- self
409
- end
410
-
411
- alias and wait
412
-
413
- def >>(*)
414
- super.tap {
415
- try
416
- }
417
- end
418
-
419
- def try
420
- if @wait.all?(&:realized?)
421
- if promise = @wait.find(&:rejected?)
422
- reject(promise.error)
423
- else
424
- resolve(@wait.map(&:value))
425
- end
426
- end
427
- end
428
- end
429
- end