opal-browser 0.1.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.yardopts +1 -0
  4. data/Gemfile +11 -0
  5. data/README.md +106 -0
  6. data/Rakefile +5 -0
  7. data/config.ru +63 -0
  8. data/lib/opal/browser.rb +4 -0
  9. data/opal-browser.gemspec +23 -0
  10. data/opal/browser.rb +10 -0
  11. data/opal/browser/animation_frame.rb +29 -0
  12. data/opal/browser/canvas.rb +277 -0
  13. data/opal/browser/canvas/data.rb +73 -0
  14. data/opal/browser/canvas/gradient.rb +37 -0
  15. data/opal/browser/canvas/style.rb +123 -0
  16. data/opal/browser/canvas/text.rb +55 -0
  17. data/opal/browser/compatibility.rb +59 -0
  18. data/opal/browser/compatibility/animation_frame.rb +93 -0
  19. data/opal/browser/compatibility/dom/document/window.rb +15 -0
  20. data/opal/browser/compatibility/dom/element/css.rb +15 -0
  21. data/opal/browser/compatibility/dom/element/matches.rb +31 -0
  22. data/opal/browser/compatibility/dom/element/offset.rb +20 -0
  23. data/opal/browser/compatibility/dom/element/scroll.rb +25 -0
  24. data/opal/browser/compatibility/dom/element/style.rb +15 -0
  25. data/opal/browser/compatibility/dom/mutation_observer.rb +47 -0
  26. data/opal/browser/compatibility/http/request.rb +15 -0
  27. data/opal/browser/compatibility/immediate.rb +107 -0
  28. data/opal/browser/compatibility/window/scroll.rb +27 -0
  29. data/opal/browser/compatibility/window/size.rb +13 -0
  30. data/opal/browser/compatibility/window/view.rb +13 -0
  31. data/opal/browser/console.rb +137 -0
  32. data/opal/browser/cookies.rb +79 -0
  33. data/opal/browser/css.rb +24 -0
  34. data/opal/browser/css/declaration.rb +88 -0
  35. data/opal/browser/css/rule.rb +48 -0
  36. data/opal/browser/css/rule/style.rb +16 -0
  37. data/opal/browser/css/style_sheet.rb +83 -0
  38. data/opal/browser/css/unit.rb +188 -0
  39. data/opal/browser/dom.rb +95 -0
  40. data/opal/browser/dom/attribute.rb +19 -0
  41. data/opal/browser/dom/builder.rb +97 -0
  42. data/opal/browser/dom/cdata.rb +9 -0
  43. data/opal/browser/dom/character_data.rb +37 -0
  44. data/opal/browser/dom/comment.rb +9 -0
  45. data/opal/browser/dom/compatibility.rb +8 -0
  46. data/opal/browser/dom/document.rb +83 -0
  47. data/opal/browser/dom/document_fragment.rb +7 -0
  48. data/opal/browser/dom/element.rb +290 -0
  49. data/opal/browser/dom/element/input.rb +17 -0
  50. data/opal/browser/dom/element/offset.rb +67 -0
  51. data/opal/browser/dom/element/position.rb +37 -0
  52. data/opal/browser/dom/element/scroll.rb +49 -0
  53. data/opal/browser/dom/event.rb +240 -0
  54. data/opal/browser/dom/event/animation.rb +26 -0
  55. data/opal/browser/dom/event/audio_processing.rb +31 -0
  56. data/opal/browser/dom/event/base.rb +207 -0
  57. data/opal/browser/dom/event/before_unload.rb +13 -0
  58. data/opal/browser/dom/event/clipboard.rb +26 -0
  59. data/opal/browser/dom/event/close.rb +35 -0
  60. data/opal/browser/dom/event/composition.rb +38 -0
  61. data/opal/browser/dom/event/custom.rb +30 -0
  62. data/opal/browser/dom/event/device_light.rb +21 -0
  63. data/opal/browser/dom/event/device_motion.rb +38 -0
  64. data/opal/browser/dom/event/device_orientation.rb +36 -0
  65. data/opal/browser/dom/event/device_proximity.rb +31 -0
  66. data/opal/browser/dom/event/drag.rb +113 -0
  67. data/opal/browser/dom/event/focus.rb +23 -0
  68. data/opal/browser/dom/event/gamepad.rb +47 -0
  69. data/opal/browser/dom/event/hash_change.rb +26 -0
  70. data/opal/browser/dom/event/keyboard.rb +93 -0
  71. data/opal/browser/dom/event/message.rb +50 -0
  72. data/opal/browser/dom/event/mouse.rb +253 -0
  73. data/opal/browser/dom/event/page_transition.rb +21 -0
  74. data/opal/browser/dom/event/pop_state.rb +21 -0
  75. data/opal/browser/dom/event/progress.rb +31 -0
  76. data/opal/browser/dom/event/sensor.rb +13 -0
  77. data/opal/browser/dom/event/storage.rb +41 -0
  78. data/opal/browser/dom/event/touch.rb +69 -0
  79. data/opal/browser/dom/event/ui.rb +22 -0
  80. data/opal/browser/dom/event/wheel.rb +49 -0
  81. data/opal/browser/dom/mutation_observer.rb +118 -0
  82. data/opal/browser/dom/node.rb +317 -0
  83. data/opal/browser/dom/node_set.rb +88 -0
  84. data/opal/browser/dom/text.rb +21 -0
  85. data/opal/browser/effects.rb +39 -0
  86. data/opal/browser/event_source.rb +67 -0
  87. data/opal/browser/history.rb +54 -0
  88. data/opal/browser/http.rb +129 -0
  89. data/opal/browser/http/binary.rb +57 -0
  90. data/opal/browser/http/compatibility.rb +1 -0
  91. data/opal/browser/http/headers.rb +90 -0
  92. data/opal/browser/http/parameters.rb +8 -0
  93. data/opal/browser/http/request.rb +331 -0
  94. data/opal/browser/http/response.rb +115 -0
  95. data/opal/browser/immediate.rb +43 -0
  96. data/opal/browser/interval.rb +93 -0
  97. data/opal/browser/location.rb +77 -0
  98. data/opal/browser/navigator.rb +151 -0
  99. data/opal/browser/screen.rb +40 -0
  100. data/opal/browser/socket.rb +115 -0
  101. data/opal/browser/storage.rb +149 -0
  102. data/opal/browser/timeout.rb +60 -0
  103. data/opal/browser/utils.rb +56 -0
  104. data/opal/browser/version.rb +3 -0
  105. data/opal/browser/window.rb +113 -0
  106. data/opal/browser/window/compatibility.rb +3 -0
  107. data/opal/browser/window/scroll.rb +49 -0
  108. data/opal/browser/window/size.rb +35 -0
  109. data/opal/browser/window/view.rb +18 -0
  110. data/spec/dom/builder_spec.rb +69 -0
  111. data/spec/dom/document_spec.rb +40 -0
  112. data/spec/dom/element_spec.rb +46 -0
  113. data/spec/dom/event_spec.rb +127 -0
  114. data/spec/dom/mutation_observer_spec.rb +37 -0
  115. data/spec/dom/node_spec.rb +154 -0
  116. data/spec/dom_spec.rb +13 -0
  117. data/spec/event_source_spec.rb +42 -0
  118. data/spec/history_spec.rb +48 -0
  119. data/spec/http_spec.rb +87 -0
  120. data/spec/immediate_spec.rb +12 -0
  121. data/spec/json2.js +486 -0
  122. data/spec/sizzle.js +5 -0
  123. data/spec/socket_spec.rb +43 -0
  124. data/spec/spec_helper.rb +37 -0
  125. data/spec/storage_spec.rb +26 -0
  126. data/spec/window_spec.rb +10 -0
  127. metadata +240 -0
@@ -0,0 +1 @@
1
+ require 'browser/compatibility/http/request'
@@ -0,0 +1,90 @@
1
+ module Browser; module HTTP
2
+
3
+ # Represents a single HTTP header.
4
+ Header = Struct.new(:name, :value)
5
+
6
+ # Represents HTTP headers.
7
+ class Headers
8
+ # Parse HTTP headers from a string.
9
+ #
10
+ # @param string [String] the whole HTTP headers response
11
+ # @return [Headers] the parsed headers
12
+ def self.parse(string)
13
+ self[string.lines.map { |l| l.chomp.split(/\s*:\s*/) }]
14
+ end
15
+
16
+ # Create {Headers} from a hash.
17
+ def self.[](hash)
18
+ result = new
19
+
20
+ hash.each {|name, value|
21
+ result[name] = value
22
+ }
23
+
24
+ result
25
+ end
26
+
27
+ include Enumerable
28
+
29
+ # Create an empty {Headers}.
30
+ def initialize
31
+ @hash = Hash.new
32
+ end
33
+
34
+ # Iterate over the headers.
35
+ #
36
+ # @yield [name, value] the header name and value
37
+ # @return [self]
38
+ def each(&block)
39
+ return enum_for :each unless block
40
+
41
+ @hash.each {|_, header|
42
+ block.call [header.name, header.value]
43
+ }
44
+
45
+ self
46
+ end
47
+
48
+ # Get the value of a header.
49
+ def [](name)
50
+ @hash[name.downcase]
51
+ end
52
+
53
+ def []=(name, value)
54
+ header = Header.new(name, value)
55
+
56
+ @hash[name.downcase] = header
57
+ end
58
+
59
+ # Push a header.
60
+ #
61
+ # @param header [Header] the header to push
62
+ # @return [self]
63
+ def <<(header)
64
+ @hash[header.name.downcase] = header
65
+
66
+ self
67
+ end
68
+
69
+ alias push <<
70
+
71
+ # Merge in place other headers.
72
+ #
73
+ # @param other [Headers, Hash, #each] the headers to merge
74
+ # @return [self]
75
+ def merge!(other)
76
+ other.each {|name, value|
77
+ self[name] = value
78
+ }
79
+
80
+ self
81
+ end
82
+
83
+ # @!attribute [r] length
84
+ # @return [Integer] the number of headers
85
+ def length
86
+ @hash.length
87
+ end
88
+ end
89
+
90
+ end; end
@@ -0,0 +1,8 @@
1
+ module Browser; module HTTP
2
+
3
+ class Parameters < Hash
4
+ def to_str
5
+ end
6
+ end
7
+
8
+ end; end
@@ -0,0 +1,331 @@
1
+ module Browser; module HTTP
2
+
3
+ class Request
4
+ include Native
5
+
6
+ # Open and send a request.
7
+ #
8
+ # @param method [Symbol] the HTTP method to use
9
+ # @param url [String, #to_s] the URL to request
10
+ # @param parameters [String, Hash] the parameters to send
11
+ #
12
+ def self.open(method, url, parameters = nil, &block)
13
+ request = new(&block)
14
+ request.open(method, url)
15
+ request.send(*parameters)
16
+ end
17
+
18
+ DEFAULT_HEADERS = {
19
+ 'X-Requested-With' => 'XMLHttpRequest',
20
+ 'X-Opal-Version' => RUBY_ENGINE_VERSION,
21
+ 'Accept' => 'text/javascript, text/html, application/xml, text/xml, */*'
22
+ }
23
+
24
+ # @!attribute [r] headers
25
+ # @return [Headers] the request headers
26
+ attr_reader :headers
27
+
28
+ # @!attribute [r] response
29
+ # @return [Response] the response associated with this request
30
+ attr_reader :response
31
+
32
+ # @!attribute [r] method
33
+ # @return [Symbol] the HTTP method for this request
34
+ attr_reader :method
35
+
36
+ # @!attribute [r] url
37
+ # @return [String, #to_s] the URL for this request
38
+ attr_reader :url
39
+
40
+ # Create a request with the optionally given configuration block.
41
+ #
42
+ # @yield [request] if the block has a parameter the request is passed
43
+ # otherwise it's instance_exec'd
44
+ def initialize(&block)
45
+ super(transport)
46
+
47
+ @headers = Headers[DEFAULT_HEADERS]
48
+ @method = :get
49
+ @asynchronous = true
50
+ @binary = false
51
+ @cacheable = true
52
+ @opened = false
53
+ @sent = false
54
+ @completed = false
55
+ @callbacks = Hash.new { |h, k| h[k] = [] }
56
+
57
+ if block.arity == 0
58
+ instance_exec(&block)
59
+ else
60
+ block.call(self)
61
+ end if block
62
+ end
63
+
64
+ def transport
65
+ `new XMLHttpRequest()`
66
+ end
67
+
68
+ # Check if the request has been opened.
69
+ def opened?
70
+ @opened
71
+ end
72
+
73
+ # Check if the request has been sent.
74
+ def sent?
75
+ @sent
76
+ end
77
+
78
+ # Check if the request has completed.
79
+ def completed?
80
+ @completed
81
+ end
82
+
83
+ # Check the request is asynchronous.
84
+ def asynchronous?
85
+ @asynchronous
86
+ end
87
+
88
+ # Check the request is synchronous.
89
+ def synchronous?
90
+ !@asynchronous
91
+ end
92
+
93
+ # Make the request asynchronous.
94
+ #
95
+ # @return [self]
96
+ def asynchronous!
97
+ @asynchronous = true
98
+
99
+ self
100
+ end
101
+
102
+ # Make the request synchronous.
103
+ #
104
+ # @return [self]
105
+ def synchronous!
106
+ @asynchronous = false
107
+
108
+ self
109
+ end
110
+
111
+ # Check the request is binary.
112
+ def binary?
113
+ @binary
114
+ end
115
+
116
+ # Make the request binary.
117
+ def binary!
118
+ @binary = true
119
+
120
+ self
121
+ end
122
+
123
+ # Check if the request is cacheable.
124
+ def cacheable?
125
+ @cacheable
126
+ end
127
+
128
+ # Disable caching for this request.
129
+ #
130
+ # @return [self]
131
+ def no_cache!
132
+ @cacheable = false
133
+
134
+ self
135
+ end
136
+
137
+ # Get or set the user used for authentication.
138
+ #
139
+ # @param value [String] when passed it sets, when omitted it gets
140
+ #
141
+ # @return [String]
142
+ def user(value = nil)
143
+ value ? @user = value : @user
144
+ end
145
+
146
+ # Get or set the password used for authentication.
147
+ #
148
+ # @param value [String] when passed it sets, when omitted it gets
149
+ #
150
+ # @return [String]
151
+ def password(value = nil)
152
+ value ? @password = value : @password
153
+ end
154
+
155
+ # Get or set the MIME type of the request.
156
+ #
157
+ # @param value [String] when passed it sets, when omitted it gets
158
+ #
159
+ # @return [String]
160
+ def mime_type(value = nil)
161
+ value ? @mime_type = value : @mime_type
162
+ end
163
+
164
+ # Get or set the Content-Type of the request.
165
+ #
166
+ # @param value [String] when passed it sets, when omitted it gets
167
+ #
168
+ # @return [String]
169
+ def content_type(value = nil)
170
+ value ? @content_type = value : @content_type
171
+ end
172
+
173
+ # Get or set the encoding of the request.
174
+ #
175
+ # @param value [String] when passed it sets, when omitted it gets
176
+ #
177
+ # @return [String]
178
+ def encoding(value = nil)
179
+ value ? @encoding = value : @encoding
180
+ end
181
+
182
+ # Set the request parameters.
183
+ #
184
+ # @param hash [Hash] the parameters
185
+ #
186
+ # @return [self]
187
+ def parameters(hash)
188
+ @parameters = hash
189
+
190
+ self
191
+ end
192
+
193
+ # Register an event on the request.
194
+ #
195
+ # @param what [Symbol, String] the event name
196
+ # @yield [response] yields the {Response}
197
+ #
198
+ # @return [self]
199
+ def on(what, &block)
200
+ @callbacks[what] << block
201
+
202
+ self
203
+ end
204
+
205
+ # Open the request.
206
+ #
207
+ # @param method [Symbol] the HTTP method to use
208
+ # @param url [String, #to_s] the URL to send the request to
209
+ # @param asynchronous [Boolean] whether the request is asynchronous or not
210
+ # @param user [String] the user to use for authentication
211
+ # @param password [String] the password to use for authentication
212
+ #
213
+ # @return [self]
214
+ def open(method = nil, url = nil, asynchronous = nil, user = nil, password = nil)
215
+ raise 'the request has already been opened' if opened?
216
+
217
+ @method = method unless method.nil?
218
+ @url = url unless url.nil?
219
+ @asynchronous = asynchronous unless asynchronous.nil?
220
+ @user = user unless user.nil?
221
+ @password = password unless password.nil?
222
+
223
+ url = @url
224
+
225
+ unless cacheable?
226
+ url += (url.include?(??) ? ?& : ??) + "_=#{rand}"
227
+ end
228
+
229
+ `#@native.open(#{@method.to_s.upcase}, #{url.to_s}, #{@asynchronous}, #{@user.to_n}, #{@password.to_n})`
230
+
231
+ unless @callbacks.empty?
232
+ `#@native.onreadystatechange = #{callback}`
233
+ end
234
+
235
+ @opened = true
236
+
237
+ self
238
+ end
239
+
240
+ # Send the request with optional parameters.
241
+ #
242
+ # @param parameters [String, Hash] the data to send
243
+ #
244
+ # @return [Response] the response
245
+ def send(parameters = @parameters)
246
+ raise 'the request has not been opened' unless opened?
247
+
248
+ raise 'the request has already been sent' if sent?
249
+
250
+ unless cacheable?
251
+ `#@native.setRequestHeader("If-Modified-Since", "Tue, 11 Sep 2001 12:46:00 GMT")`
252
+ end
253
+
254
+ @headers.each {|name, value|
255
+ `#@native.setRequestHeader(#{name.to_s}, #{value.to_s})`
256
+ }
257
+
258
+ if @content_type
259
+ header = @content_type
260
+ header += "; charset=#{@encoding}" if @encoding
261
+
262
+ `#@native.setRequestHeader('Content-Type', header)`
263
+ end
264
+
265
+ if binary?
266
+ if Buffer.supported?
267
+ `#@native.responseType = 'arraybuffer'`
268
+ else
269
+ `#@native.overrideMimeType('text/plain; charset=x-user-defined')`
270
+ end
271
+ end
272
+
273
+ if mime_type && !binary?
274
+ `#@native.overrideMimeType(#@mime_type)`
275
+ end
276
+
277
+ @sent = true
278
+ @response = Response.new(self)
279
+
280
+ if String === parameters
281
+ data = parameters
282
+ elsif Hash === parameters
283
+ data = parameters.map {|vals|
284
+ vals.map(&:encode_uri_component).join(?=)
285
+ }.join(?&)
286
+
287
+ unless @content_type
288
+ `#@native.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')`
289
+ end
290
+ else
291
+ data = `null`
292
+ end
293
+
294
+ `#@native.send(#{data})`
295
+
296
+ @response
297
+ end
298
+
299
+ # Abort the request.
300
+ #
301
+ # @return [self]
302
+ def abort
303
+ `#@native.abort()`
304
+
305
+ self
306
+ end
307
+
308
+ private
309
+ def callback
310
+ proc {|event|
311
+ state = %w[uninitialized loading loaded interactive complete][`#@native.readyState`]
312
+ res = response
313
+
314
+ @callbacks[state].each { |b| b.(res) }
315
+
316
+ if state == :complete
317
+ @completed = true
318
+
319
+ @callbacks[res.status.code].each { |b| b.(res) }
320
+
321
+ if res.success?
322
+ @callbacks[:success].each { |b| b.(res) }
323
+ else
324
+ @callbacks[:failure].each { |b| b.(res) }
325
+ end
326
+ end
327
+ }.to_n
328
+ end
329
+ end
330
+
331
+ end; end
@@ -0,0 +1,115 @@
1
+ require 'json'
2
+
3
+ module Browser; module HTTP
4
+
5
+ # Represents an HTTP response.
6
+ class Response
7
+ include Native
8
+
9
+ Status = Struct.new(:code, :text)
10
+
11
+ # @!attribute [r] request
12
+ # @return [Request] the request to this response
13
+ attr_reader :request
14
+
15
+ # Create a response from a request.
16
+ #
17
+ # @param request [Request] the request
18
+ def initialize(request)
19
+ super(request.to_n)
20
+
21
+ @request = request
22
+ end
23
+
24
+ # @!attribute [r] headers
25
+ # @return [Headers] the response headers
26
+ def headers
27
+ @headers ||= Headers.parse(`#@native.getAllResponseHeaders()`)
28
+ end
29
+
30
+ # @!attribute [r] status
31
+ # @return [Status] the response status
32
+ def status
33
+ Status.new(`#@native.status || nil`, `#@native.statusText || nil`)
34
+ end
35
+
36
+ # Checks if the response was successful
37
+ def success?
38
+ if code = status.code
39
+ code >= 200 && code < 300 || code == 304
40
+ else
41
+ false
42
+ end
43
+ end
44
+
45
+ # Check if the response failed
46
+ def failure?
47
+ !success?
48
+ end
49
+
50
+ # @!attribute [r] text
51
+ # @return [String] the response body as text
52
+ def text
53
+ %x{
54
+ var result = #@native.responseText;
55
+
56
+ if (!result) {
57
+ return nil;
58
+ }
59
+
60
+ return result;
61
+ }
62
+ end
63
+
64
+ # @!attribute [r] json
65
+ # @return [Hash, Array] the response body as JSON
66
+ def json
67
+ %x{
68
+ var result = #@native.responseText;
69
+
70
+ if (!result) {
71
+ return nil;
72
+ }
73
+
74
+ return #{JSON.parse(`result`)};
75
+ }
76
+ end
77
+
78
+ # @!attribute [r] xml
79
+ # @return [DOM::Document] the response body as DOM document
80
+ def xml
81
+ %x{
82
+ var result = #@native.responseXML;
83
+
84
+ if (!result) {
85
+ return nil;
86
+ }
87
+ }
88
+
89
+ DOM(`result`)
90
+ end
91
+
92
+ # @!attribute [r] binary
93
+ # @return [Binary] the response body as binary
94
+ def binary
95
+ return unless request.binary?
96
+
97
+ if Buffer.supported?
98
+ %x{
99
+ var result = #@native.response;
100
+
101
+ if (!result) {
102
+ return nil;
103
+ }
104
+ }
105
+
106
+ Binary.new(Buffer.new(`result`))
107
+ else
108
+ return unless text
109
+
110
+ Binary.new(text)
111
+ end
112
+ end
113
+ end
114
+
115
+ end; end