volt 0.9.1.pre1 → 0.9.1.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/Gemfile +8 -0
  4. data/VERSION +1 -1
  5. data/app/volt/tasks/live_query/live_query.rb +8 -2
  6. data/app/volt/tasks/query_tasks.rb +2 -1
  7. data/lib/volt/boot.rb +6 -6
  8. data/lib/volt/cli.rb +22 -17
  9. data/lib/volt/cli/asset_compile.rb +8 -4
  10. data/lib/volt/cli/console.rb +1 -0
  11. data/lib/volt/controllers/model_controller.rb +1 -1
  12. data/lib/volt/extra_core/logger.rb +4 -0
  13. data/lib/volt/models/validators/unique_validator.rb +8 -6
  14. data/lib/volt/page/bindings/attribute_binding.rb +1 -1
  15. data/lib/volt/page/channel.rb +10 -4
  16. data/lib/volt/page/page.rb +1 -1
  17. data/lib/volt/page/string_template_renderer.rb +3 -3
  18. data/lib/volt/server.rb +55 -81
  19. data/lib/volt/server/component_handler.rb +16 -8
  20. data/lib/volt/server/forking_server.rb +176 -0
  21. data/lib/volt/server/html_parser/attribute_scope.rb +1 -1
  22. data/lib/volt/server/html_parser/sandlebars_parser.rb +5 -8
  23. data/lib/volt/server/rack/http_request.rb +3 -1
  24. data/lib/volt/server/rack/http_resource.rb +3 -1
  25. data/lib/volt/server/rack/opal_files.rb +14 -0
  26. data/lib/volt/server/socket_connection_handler.rb +12 -16
  27. data/lib/volt/server/websocket/rack_server_adaptor.rb +19 -0
  28. data/lib/volt/server/websocket/websocket_handler.rb +42 -0
  29. data/lib/volt/spec/capybara.rb +18 -7
  30. data/lib/volt/spec/setup.rb +7 -2
  31. data/lib/volt/tasks/dispatcher.rb +4 -0
  32. data/lib/volt/utils/generic_pool.rb +6 -0
  33. data/lib/volt/utils/read_write_lock.rb +173 -0
  34. data/lib/volt/volt/app.rb +46 -0
  35. data/lib/volt/volt/core.rb +3 -0
  36. data/spec/apps/kitchen_sink/Gemfile +0 -4
  37. data/spec/integration/flash_spec.rb +1 -0
  38. data/spec/integration/user_spec.rb +0 -2
  39. data/spec/server/html_parser/view_parser_spec.rb +1 -1
  40. data/spec/server/rack/asset_files_spec.rb +1 -1
  41. data/spec/spec_helper.rb +12 -0
  42. data/templates/project/Gemfile.tt +2 -0
  43. data/templates/project/config/app.rb.tt +2 -2
  44. data/templates/project/config/base/index.html +1 -0
  45. data/volt.gemspec +5 -1
  46. metadata +53 -7
  47. data/app/volt/assets/js/sockjs-0.3.4.min.js +0 -27
  48. data/lib/volt/server/rack/component_html_renderer.rb +0 -22
@@ -1,3 +1,7 @@
1
+ if RUBY_PLATFORM != 'opal'
2
+ require 'volt/volt/core'
3
+ end
4
+
1
5
  module Volt
2
6
  class << self
3
7
  def spec_setup(app_path = '.')
@@ -9,15 +13,16 @@ module Volt
9
13
  require 'volt/boot'
10
14
 
11
15
  # Require in app
12
- Volt.boot(app_path)
16
+ volt_app = Volt.boot(app_path)
13
17
 
14
18
  unless RUBY_PLATFORM == 'opal'
15
19
  begin
16
20
  require 'volt/spec/capybara'
17
21
 
18
- setup_capybara(app_path)
22
+ setup_capybara(app_path, volt_app)
19
23
  rescue LoadError => e
20
24
  Volt.logger.warn("unable to load capybara, if you wish to use it for tests, be sure it is in the app's Gemfile")
25
+ Volt.logger.error(e)
21
26
  end
22
27
  end
23
28
 
@@ -1,10 +1,14 @@
1
1
  # require 'ruby-prof'
2
2
  require 'volt/utils/logging/task_logger'
3
+ require 'drb'
3
4
 
4
5
  module Volt
5
6
  # The task dispatcher is responsible for taking incoming messages
6
7
  # from the socket channel and dispatching them to the proper handler.
7
8
  class Dispatcher
9
+ # When we pass the dispatcher over DRb, don't send a copy, just proxy.
10
+ include DRb::DRbUndumped
11
+
8
12
  # Dispatch takes an incoming Task from the client and runs it on the
9
13
  # server, returning the result to the client.
10
14
  # Tasks returning a promise will wait to return.
@@ -9,6 +9,8 @@ module Volt
9
9
  # all of the items at a sub-path with #lookup_all
10
10
  #
11
11
  # TODO: make the lookup/create threadsafe
12
+ class GenericPoolDeleteException < StandardError ; end
13
+
12
14
  class GenericPool
13
15
  attr_reader :pool
14
16
 
@@ -93,6 +95,10 @@ module Volt
93
95
  stack << section
94
96
 
95
97
  if args.size - 1 == index
98
+ unless section
99
+ raise GenericPoolDeleteException, "An attempt was made to delete at #{arg}, full path: #{args.inspect} in #{inspect}"
100
+ end
101
+
96
102
  section.delete(arg)
97
103
  else
98
104
  section = section[arg]
@@ -0,0 +1,173 @@
1
+ # Currently the released gem version of the concurrent-ruby gem does not have the ReadWriteLock
2
+ # relased in it (it is on master).
3
+
4
+ # Ruby read-write lock implementation
5
+ # Allows any number of concurrent readers, but only one concurrent writer
6
+ # (And if the "write" lock is taken, any readers who come along will have to wait)
7
+
8
+ # If readers are already active when a writer comes along, the writer will wait for
9
+ # all the readers to finish before going ahead
10
+ # But any additional readers who come when the writer is already waiting, will also
11
+ # wait (so writers are not starved)
12
+
13
+ # Written by Alex Dowad
14
+ # Bug fixes contributed by Alex Kliuchnikau
15
+ # Suggestion on avoiding reader starvation contributed by maniek
16
+ # Thanks to Doug Lea for java.util.concurrent.ReentrantReadWriteLock (used for inspiration)
17
+
18
+ # Usage:
19
+ # lock = ReadWriteLock.new
20
+ # lock.with_read_lock { data.retrieve }
21
+ # lock.with_write_lock { data.modify! }
22
+
23
+ # NOTE: DON'T try to acquire the write lock while already holding a read lock!
24
+ # OR try to acquire the write lock while you already have it
25
+ # It will lead to deadlock
26
+
27
+ # Implementation notes:
28
+ # A goal is to make the uncontended path for both readers/writers lock-free
29
+ # Only if there is reader-writer or writer-writer contention, should locks be used
30
+ # Internal state is represented by a single integer ("counter"), and updated
31
+ # using atomic compare-and-swap operations
32
+ # When the counter is 0, the lock is free
33
+ # Each reader increments the counter by 1 when acquiring a read lock
34
+ # (and decrements by 1 when releasing the read lock)
35
+ # The counter is increased by (1 << 15) for each writer waiting to acquire the
36
+ # write lock, and by (1 << 30) if the write lock is taken
37
+
38
+ require 'rubygems' # for compatibility with JRuby, MRI 1.8, etc
39
+ require 'concurrent/atomic'
40
+ require 'thread'
41
+
42
+ class ReadWriteLock
43
+ def initialize
44
+ @counter = Concurrent::Atomic.new(0) # single integer which represents lock state
45
+ @reader_q = ConditionVariable.new # queue for waiting readers
46
+ @reader_mutex = Mutex.new # to protect reader queue
47
+ @writer_q = ConditionVariable.new # queue for waiting writers
48
+ @writer_mutex = Mutex.new # to protect writer queue
49
+ end
50
+
51
+ WAITING_WRITER = 1 << 15
52
+ RUNNING_WRITER = 1 << 30
53
+ MAX_READERS = WAITING_WRITER - 1
54
+ MAX_WRITERS = RUNNING_WRITER - MAX_READERS - 1
55
+
56
+ def with_read_lock
57
+ acquire_read_lock
58
+ result = yield
59
+ release_read_lock
60
+ result
61
+ end
62
+
63
+ def with_write_lock
64
+ acquire_write_lock
65
+ result = yield
66
+ release_write_lock
67
+ result
68
+ end
69
+
70
+ def acquire_read_lock
71
+ while(true)
72
+ c = @counter.value
73
+ raise "Too many reader threads!" if (c & MAX_READERS) == MAX_READERS
74
+
75
+ # If a writer is waiting when we first queue up, we need to wait
76
+ if c >= WAITING_WRITER
77
+ # But it is possible that the writer could finish and decrement @counter right here...
78
+ @reader_mutex.synchronize do
79
+ # So check again inside the synchronized section
80
+ @reader_q.wait(@reader_mutex) if @counter.value >= WAITING_WRITER
81
+ end
82
+
83
+ # after a reader has waited once, they are allowed to "barge" ahead of waiting writers
84
+ # but if a writer is *running*, the reader still needs to wait (naturally)
85
+ while(true)
86
+ c = @counter.value
87
+ if c >= RUNNING_WRITER
88
+ @reader_mutex.synchronize do
89
+ @reader_q.wait(@reader_mutex) if @counter.value >= RUNNING_WRITER
90
+ end
91
+ else
92
+ return if @counter.compare_and_swap(c,c+1)
93
+ end
94
+ end
95
+ else
96
+ break if @counter.compare_and_swap(c,c+1)
97
+ end
98
+ end
99
+ end
100
+
101
+ def release_read_lock
102
+ while(true)
103
+ c = @counter.value
104
+ if @counter.compare_and_swap(c,c-1)
105
+ # If one or more writers were waiting, and we were the last reader, wake a writer up
106
+ if c >= WAITING_WRITER && (c & MAX_READERS) == 1
107
+ @writer_mutex.synchronize { @writer_q.signal }
108
+ end
109
+ break
110
+ end
111
+ end
112
+ end
113
+
114
+ def acquire_write_lock
115
+ while(true)
116
+ c = @counter.value
117
+ raise "Too many writers!" if (c & MAX_WRITERS) == MAX_WRITERS
118
+
119
+ if c == 0 # no readers OR writers running
120
+ # if we successfully swap the RUNNING_WRITER bit on, then we can go ahead
121
+ break if @counter.compare_and_swap(0,RUNNING_WRITER)
122
+ elsif @counter.compare_and_swap(c,c+WAITING_WRITER)
123
+ while(true)
124
+ # Now we have successfully incremented, so no more readers will be able to increment
125
+ # (they will wait instead)
126
+ # However, readers OR writers could decrement right here, OR another writer could increment
127
+ @writer_mutex.synchronize do
128
+ # So we have to do another check inside the synchronized section
129
+ # If a writer OR reader is running, then go to sleep
130
+ c = @counter.value
131
+ @writer_q.wait(@writer_mutex) if (c >= RUNNING_WRITER) || ((c & MAX_READERS) > 0)
132
+ end
133
+
134
+ # We just came out of a wait
135
+ # If we successfully turn the RUNNING_WRITER bit on with an atomic swap,
136
+ # Then we are OK to stop waiting and go ahead
137
+ # Otherwise go back and wait again
138
+ c = @counter.value
139
+ break if (c < RUNNING_WRITER) &&
140
+ ((c & MAX_READERS) == 0) &&
141
+ @counter.compare_and_swap(c,c+RUNNING_WRITER-WAITING_WRITER)
142
+ end
143
+ break
144
+ end
145
+ end
146
+ end
147
+
148
+ def release_write_lock
149
+ while(true)
150
+ c = @counter.value
151
+ if @counter.compare_and_swap(c,c-RUNNING_WRITER)
152
+ @reader_mutex.synchronize { @reader_q.broadcast }
153
+ if (c & MAX_WRITERS) > 0 # if any writers are waiting...
154
+ @writer_mutex.synchronize { @writer_q.signal }
155
+ end
156
+ break
157
+ end
158
+ end
159
+ end
160
+
161
+ def to_s
162
+ c = @counter.value
163
+ s = if c >= RUNNING_WRITER
164
+ "1 writer running, "
165
+ elsif (c & MAX_READERS) > 0
166
+ "#{c & MAX_READERS} readers running, "
167
+ else
168
+ ""
169
+ end
170
+
171
+ "#<ReadWriteLock:#{object_id.to_s(16)} #{s}#{(c & MAX_WRITERS) / WAITING_WRITER} writers waiting>"
172
+ end
173
+ end
@@ -0,0 +1,46 @@
1
+ module Volt
2
+ class App
3
+ attr_reader :component_paths, :router
4
+
5
+ def initialize(app_path)
6
+ # Setup root path
7
+ Volt.root = app_path
8
+
9
+ # Require in config files
10
+ unless RUBY_PLATFORM == 'opal'
11
+ Volt.run_files_in_config_folder
12
+ end
13
+
14
+ # Load component paths
15
+ @component_paths = ComponentPaths.new(app_path)
16
+ @component_paths.require_in_components
17
+
18
+ unless RUBY_PLATFORM == 'opal'
19
+ setup_router
20
+ require_http_controllers
21
+ end
22
+ end
23
+
24
+ unless RUBY_PLATFORM == 'opal'
25
+ def setup_router
26
+ # Find the route file
27
+ home_path = @component_paths.component_paths('main').first
28
+ routes = File.read("#{home_path}/config/routes.rb")
29
+ @router = Routes.new.define do
30
+ eval(routes)
31
+ end
32
+ end
33
+
34
+ def require_http_controllers
35
+ @component_paths.app_folders do |app_folder|
36
+ # Sort so we get consistent load order across platforms
37
+ Dir["#{app_folder}/*/controllers/server/*.rb"].each do |ruby_file|
38
+ #path = ruby_file.gsub(/^#{app_folder}\//, '')[0..-4]
39
+ #require(path)
40
+ load ruby_file
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,3 @@
1
+ # Require in the core volt classes that get used on the server
2
+ require 'volt/controllers/http_controller'
3
+ require 'volt/server/rack/http_request'
@@ -25,7 +25,3 @@ end
25
25
  platform :jruby do
26
26
  gem 'jubilee'
27
27
  end
28
-
29
- #---------------------
30
- # Needed at the moment
31
- gem 'volt-sockjs', require: false, platforms: :mri
@@ -10,6 +10,7 @@ if ENV['BROWSER'] && ENV['BROWSER'] != 'sauce'
10
10
 
11
11
  click_link 'Flash Notice'
12
12
  expect(page).to have_content('A notice message')
13
+ # sleep 40
13
14
  find('.alert').click
14
15
  expect(page).to_not have_content('A notice message')
15
16
 
@@ -14,8 +14,6 @@ describe 'user accounts', type: :feature, sauce: true do
14
14
  it 'should create an account' do
15
15
  visit '/'
16
16
 
17
- # sleep 300
18
-
19
17
  click_link 'Login'
20
18
 
21
19
  click_link 'Signup here'
@@ -156,7 +156,7 @@ describe Volt::ViewParser do
156
156
  'html' => " <div id=\"id0\">\n </div>\n",
157
157
  'bindings' => {
158
158
  'id0' => [
159
- "lambda { |__p, __t, __c, __id| Volt::AttributeBinding.new(__p, __t, __c, __id, \"class\", Proc.new { Volt::StringTemplateRender.new(__p, __c, \"main/main/main/body/_rv1\") }) }"
159
+ "lambda { |__p, __t, __c, __id| Volt::AttributeBinding.new(__p, __t, __c, __id, \"class\", Proc.new { Volt::StringTemplateRenderer.new(__p, __c, \"main/main/main/body/_rv1\") }) }"
160
160
  ]
161
161
  }
162
162
  })
@@ -19,7 +19,7 @@ if RUBY_PLATFORM != 'opal'
19
19
  it 'should list all JS files' do
20
20
  main = Volt::AssetFiles.new('main', @component_paths)
21
21
 
22
- expect(main.javascript_files(nil)).to eq(['/assets/js/jquery-2.0.3.js', '/assets/js/sockjs-0.3.4.min.js', '/assets/js/volt_js_polyfills.js', '/assets/js/bootstrap.js', '/assets/js/test2.js', '/assets/js/test3.js', '/assets/js/test1.js', '/assets/volt/page/page.js', '/components/main.js'])
22
+ expect(main.javascript_files(nil)).to eq(['/assets/js/jquery-2.0.3.js', '/assets/js/volt_js_polyfills.js', '/assets/js/bootstrap.js', '/assets/js/test2.js', '/assets/js/test3.js', '/assets/js/test1.js', '/assets/volt/page/page.js', '/components/main.js'])
23
23
  end
24
24
 
25
25
  it 'should raise an exception for a missing component gem' do
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,19 @@
1
+
1
2
  require 'volt/spec/setup'
2
3
 
3
4
  unless RUBY_PLATFORM == 'opal'
4
5
  require 'pry-byebug'
6
+ require 'coveralls'
7
+ Coveralls.wear!
8
+
9
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
10
+ SimpleCov::Formatter::HTMLFormatter,
11
+ Coveralls::SimpleCov::Formatter
12
+ ]
13
+
14
+ SimpleCov.start do
15
+ add_filter 'spec/'
16
+ end
5
17
  end
6
18
 
7
19
  # Specs are run against the kitchen sink app
@@ -24,6 +24,8 @@ end
24
24
 
25
25
  # Server for MRI
26
26
  platform :mri do
27
+ # The implementation of ReadWriteLock in Volt uses concurrent ruby and ext helps performance.
28
+ gem 'concurrent-ruby-ext', '~> 0.8.0'
27
29
  gem 'thin', '~> 1.6.0'
28
30
  gem 'bson_ext', '~> 1.9.0'
29
31
  end
@@ -5,7 +5,7 @@ Volt.configure do |config|
5
5
  # be tampered with. A random value is generated on new projects that will work
6
6
  # without the need to customize. Make sure this value doesn't leave your server.
7
7
  #
8
- # For added security we reccomend moving the app secret into an enviromnet. You can
8
+ # For added security we recommend moving the app secret into an environment. You can
9
9
  # setup that like so:
10
10
  #
11
11
  # config.app_secret = ENV['APP_SECRET']
@@ -38,4 +38,4 @@ Volt.configure do |config|
38
38
  # Use username instead of email as the login
39
39
  # config.public.auth.use_username = true
40
40
 
41
- end
41
+ end
@@ -2,6 +2,7 @@
2
2
  <html>
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
+ <%# This file is rendered on the server and does not uses erb instead of Volt's normal template system. You can add to it, but keep in mind the template language difference. It handles auto-loading all JS/Opal and Css %>
5
6
  <% javascript_files.each do |javascript_file| %>
6
7
  <script src="<%= javascript_file %>"></script>
7
8
  <% end %>
data/volt.gemspec CHANGED
@@ -32,7 +32,8 @@ Gem::Specification.new do |spec|
32
32
  spec.add_dependency 'opal', '~> 0.7.1'
33
33
  spec.add_dependency 'opal-jquery', '~> 0.3.0'
34
34
  spec.add_dependency 'bundler', '>= 1.5'
35
- spec.add_dependency 'volt-sockjs', '~> 0.3.4.4'
35
+ spec.add_dependency 'faye-websocket', '~> 0.9.2'
36
+ spec.add_dependency 'concurrent-ruby', '~> 0.8.0'
36
37
 
37
38
  # For user passwords
38
39
  spec.add_dependency 'bcrypt', '~> 3.1.9'
@@ -44,6 +45,9 @@ Gem::Specification.new do |spec|
44
45
  spec.add_development_dependency 'selenium-webdriver', '~> 2.43.0'
45
46
  spec.add_development_dependency 'chromedriver2-helper', '~> 0.0.8'
46
47
  spec.add_development_dependency 'poltergeist', '~> 1.5.0'
48
+ # spec.add_development_dependency 'puma', '~> 2.11.2'
49
+ spec.add_development_dependency 'thin', '~> 1.6.3'
50
+ spec.add_development_dependency 'coveralls', '~> 0.8.1'
47
51
 
48
52
  spec.add_development_dependency 'guard', '2.6.0' # bug in current guard
49
53
  spec.add_development_dependency 'guard-rspec', '~> 4.3.0'
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.1.pre1
4
+ version: 0.9.1.pre2
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-04-22 00:00:00.000000000 Z
11
+ date: 2015-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -193,19 +193,33 @@ dependencies:
193
193
  - !ruby/object:Gem::Version
194
194
  version: '1.5'
195
195
  - !ruby/object:Gem::Dependency
196
- name: volt-sockjs
196
+ name: faye-websocket
197
197
  requirement: !ruby/object:Gem::Requirement
198
198
  requirements:
199
199
  - - "~>"
200
200
  - !ruby/object:Gem::Version
201
- version: 0.3.4.4
201
+ version: 0.9.2
202
202
  type: :runtime
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
206
  - - "~>"
207
207
  - !ruby/object:Gem::Version
208
- version: 0.3.4.4
208
+ version: 0.9.2
209
+ - !ruby/object:Gem::Dependency
210
+ name: concurrent-ruby
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: 0.8.0
216
+ type: :runtime
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: 0.8.0
209
223
  - !ruby/object:Gem::Dependency
210
224
  name: bcrypt
211
225
  requirement: !ruby/object:Gem::Requirement
@@ -304,6 +318,34 @@ dependencies:
304
318
  - - "~>"
305
319
  - !ruby/object:Gem::Version
306
320
  version: 1.5.0
321
+ - !ruby/object:Gem::Dependency
322
+ name: thin
323
+ requirement: !ruby/object:Gem::Requirement
324
+ requirements:
325
+ - - "~>"
326
+ - !ruby/object:Gem::Version
327
+ version: 1.6.3
328
+ type: :development
329
+ prerelease: false
330
+ version_requirements: !ruby/object:Gem::Requirement
331
+ requirements:
332
+ - - "~>"
333
+ - !ruby/object:Gem::Version
334
+ version: 1.6.3
335
+ - !ruby/object:Gem::Dependency
336
+ name: coveralls
337
+ requirement: !ruby/object:Gem::Requirement
338
+ requirements:
339
+ - - "~>"
340
+ - !ruby/object:Gem::Version
341
+ version: 0.8.1
342
+ type: :development
343
+ prerelease: false
344
+ version_requirements: !ruby/object:Gem::Requirement
345
+ requirements:
346
+ - - "~>"
347
+ - !ruby/object:Gem::Version
348
+ version: 0.8.1
307
349
  - !ruby/object:Gem::Dependency
308
350
  name: guard
309
351
  requirement: !ruby/object:Gem::Requirement
@@ -453,7 +495,6 @@ files:
453
495
  - VERSION
454
496
  - app/volt/assets/css/notices.css.scss
455
497
  - app/volt/assets/js/jquery-2.0.3.js
456
- - app/volt/assets/js/sockjs-0.3.4.min.js
457
498
  - app/volt/assets/js/volt_js_polyfills.js
458
499
  - app/volt/config/dependencies.rb
459
500
  - app/volt/controllers/notices_controller.rb
@@ -585,6 +626,7 @@ files:
585
626
  - lib/volt/server/banner.txt
586
627
  - lib/volt/server/component_handler.rb
587
628
  - lib/volt/server/component_templates.rb
629
+ - lib/volt/server/forking_server.rb
588
630
  - lib/volt/server/html_parser/attribute_scope.rb
589
631
  - lib/volt/server/html_parser/component_view_scope.rb
590
632
  - lib/volt/server/html_parser/each_scope.rb
@@ -596,7 +638,6 @@ files:
596
638
  - lib/volt/server/html_parser/view_scope.rb
597
639
  - lib/volt/server/rack/asset_files.rb
598
640
  - lib/volt/server/rack/component_code.rb
599
- - lib/volt/server/rack/component_html_renderer.rb
600
641
  - lib/volt/server/rack/component_paths.rb
601
642
  - lib/volt/server/rack/http_request.rb
602
643
  - lib/volt/server/rack/http_resource.rb
@@ -608,6 +649,8 @@ files:
608
649
  - lib/volt/server/rack/source_map_server.rb
609
650
  - lib/volt/server/socket_connection_handler.rb
610
651
  - lib/volt/server/socket_connection_handler_stub.rb
652
+ - lib/volt/server/websocket/rack_server_adaptor.rb
653
+ - lib/volt/server/websocket/websocket_handler.rb
611
654
  - lib/volt/spec/capybara.rb
612
655
  - lib/volt/spec/sauce_labs.rb
613
656
  - lib/volt/spec/setup.rb
@@ -624,9 +667,12 @@ files:
624
667
  - lib/volt/utils/logging/task_logger.rb
625
668
  - lib/volt/utils/modes.rb
626
669
  - lib/volt/utils/promise_patch.rb
670
+ - lib/volt/utils/read_write_lock.rb
627
671
  - lib/volt/utils/tilt_patch.rb
628
672
  - lib/volt/utils/timers.rb
629
673
  - lib/volt/utils/volt_user_error.rb
674
+ - lib/volt/volt/app.rb
675
+ - lib/volt/volt/core.rb
630
676
  - lib/volt/volt/environment.rb
631
677
  - lib/volt/volt/users.rb
632
678
  - spec/apps/file_loading/app/bootstrap/assets/js/bootstrap.js