opal-browser 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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