opal-browser 0.1.0.beta1 → 0.2.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.
- checksums.yaml +4 -4
- data/.travis.yml +60 -0
- data/.yardopts +1 -1
- data/Gemfile +7 -2
- data/LICENSE +19 -0
- data/README.md +74 -10
- data/config.ru +2 -1
- data/index.html.erb +22 -0
- data/opal-browser.gemspec +9 -11
- data/opal/browser.rb +1 -1
- data/opal/browser/animation_frame.rb +66 -9
- data/opal/browser/canvas.rb +72 -18
- data/opal/browser/canvas/data.rb +1 -1
- data/opal/browser/console.rb +3 -37
- data/opal/browser/cookies.rb +80 -24
- data/opal/browser/css/declaration.rb +0 -5
- data/opal/browser/{timeout.rb → delay.rb} +13 -13
- data/opal/browser/dom.rb +0 -2
- data/opal/browser/dom/attribute.rb +6 -0
- data/opal/browser/dom/builder.rb +4 -8
- data/opal/browser/dom/character_data.rb +43 -7
- data/opal/browser/dom/document.rb +13 -11
- data/opal/browser/dom/element.rb +127 -29
- data/opal/browser/dom/element/image.rb +23 -0
- data/opal/browser/dom/element/offset.rb +27 -10
- data/opal/browser/dom/element/scroll.rb +32 -12
- data/opal/browser/dom/element/size.rb +29 -0
- data/opal/browser/dom/event.rb +88 -75
- data/opal/browser/dom/event/animation.rb +16 -4
- data/opal/browser/dom/event/audio_processing.rb +6 -4
- data/opal/browser/dom/event/base.rb +229 -64
- data/opal/browser/dom/event/before_unload.rb +6 -4
- data/opal/browser/dom/event/clipboard.rb +6 -4
- data/opal/browser/dom/event/close.rb +16 -4
- data/opal/browser/dom/event/composition.rb +16 -4
- data/opal/browser/dom/event/custom.rb +43 -8
- data/opal/browser/dom/event/device_light.rb +6 -4
- data/opal/browser/dom/event/device_motion.rb +17 -4
- data/opal/browser/dom/event/device_orientation.rb +16 -4
- data/opal/browser/dom/event/device_proximity.rb +6 -4
- data/opal/browser/dom/event/drag.rb +34 -28
- data/opal/browser/dom/event/focus.rb +21 -5
- data/opal/browser/dom/event/gamepad.rb +33 -20
- data/opal/browser/dom/event/hash_change.rb +6 -4
- data/opal/browser/dom/event/keyboard.rb +45 -23
- data/opal/browser/dom/event/message.rb +28 -8
- data/opal/browser/dom/event/mouse.rb +26 -25
- data/opal/browser/dom/event/page_transition.rb +6 -4
- data/opal/browser/dom/event/pop_state.rb +16 -4
- data/opal/browser/dom/event/progress.rb +16 -4
- data/opal/browser/dom/event/sensor.rb +6 -4
- data/opal/browser/dom/event/storage.rb +6 -4
- data/opal/browser/dom/event/touch.rb +10 -19
- data/opal/browser/dom/event/ui.rb +19 -3
- data/opal/browser/dom/event/wheel.rb +2 -2
- data/opal/browser/dom/mutation_observer.rb +65 -5
- data/opal/browser/dom/node.rb +164 -59
- data/opal/browser/dom/node_set.rb +4 -0
- data/opal/browser/dom/text.rb +16 -1
- data/opal/browser/event_source.rb +5 -2
- data/opal/browser/history.rb +51 -15
- data/opal/browser/http.rb +22 -7
- data/opal/browser/http/headers.rb +5 -0
- data/opal/browser/http/request.rb +40 -10
- data/opal/browser/immediate.rb +123 -9
- data/opal/browser/interval.rb +8 -13
- data/opal/browser/location.rb +13 -3
- data/opal/browser/navigator.rb +9 -6
- data/opal/browser/screen.rb +31 -5
- data/opal/browser/socket.rb +8 -4
- data/opal/browser/storage.rb +118 -33
- data/opal/browser/support.rb +232 -0
- data/opal/browser/utils.rb +24 -6
- data/opal/browser/version.rb +1 -1
- data/opal/browser/window.rb +1 -2
- data/opal/browser/window/scroll.rb +21 -11
- data/opal/browser/window/size.rb +16 -6
- data/opal/browser/window/view.rb +23 -5
- data/spec/dom/builder_spec.rb +19 -19
- data/spec/dom/document_spec.rb +6 -6
- data/spec/dom/element_spec.rb +5 -5
- data/spec/dom/event_spec.rb +20 -20
- data/spec/dom/mutation_observer_spec.rb +5 -5
- data/spec/dom/node_spec.rb +39 -27
- data/spec/dom_spec.rb +10 -8
- data/spec/event_source_spec.rb +12 -12
- data/spec/history_spec.rb +24 -15
- data/spec/http_spec.rb +18 -17
- data/spec/immediate_spec.rb +9 -7
- data/spec/runner.rb +114 -0
- data/spec/socket_spec.rb +8 -8
- data/spec/spec_helper.rb +1 -0
- data/spec/storage_spec.rb +6 -6
- data/spec/wgxpath.install.js +49 -0
- data/spec/window_spec.rb +2 -2
- metadata +21 -54
- data/opal/browser/compatibility.rb +0 -59
- data/opal/browser/compatibility/animation_frame.rb +0 -93
- data/opal/browser/compatibility/dom/document/window.rb +0 -15
- data/opal/browser/compatibility/dom/element/css.rb +0 -15
- data/opal/browser/compatibility/dom/element/matches.rb +0 -31
- data/opal/browser/compatibility/dom/element/offset.rb +0 -20
- data/opal/browser/compatibility/dom/element/scroll.rb +0 -25
- data/opal/browser/compatibility/dom/element/style.rb +0 -15
- data/opal/browser/compatibility/dom/mutation_observer.rb +0 -47
- data/opal/browser/compatibility/http/request.rb +0 -15
- data/opal/browser/compatibility/immediate.rb +0 -107
- data/opal/browser/compatibility/window/scroll.rb +0 -27
- data/opal/browser/compatibility/window/size.rb +0 -13
- data/opal/browser/compatibility/window/view.rb +0 -13
- data/opal/browser/dom/compatibility.rb +0 -8
- data/opal/browser/http/compatibility.rb +0 -1
- data/opal/browser/window/compatibility.rb +0 -3
data/opal/browser/dom/text.rb
CHANGED
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
module Browser; module DOM
|
|
2
2
|
|
|
3
|
+
# Encapsulates a text node.
|
|
4
|
+
#
|
|
5
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/Text
|
|
3
6
|
class Text < CharacterData
|
|
7
|
+
# (see Document#create_text)
|
|
4
8
|
def self.create(*args)
|
|
5
9
|
$document.create_text(*args)
|
|
6
10
|
end
|
|
7
11
|
|
|
12
|
+
# @!attribute [r] whole
|
|
13
|
+
# @return [String] the whole text
|
|
14
|
+
#
|
|
15
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/Text.wholeText
|
|
8
16
|
def whole
|
|
9
17
|
`#@native.wholeText`
|
|
10
18
|
end
|
|
11
19
|
|
|
20
|
+
# Split the text node at a given offset.
|
|
21
|
+
#
|
|
22
|
+
# @param offset [Integer] the offset where to split the text node
|
|
23
|
+
#
|
|
24
|
+
# @return [Text] the newly created text node
|
|
25
|
+
#
|
|
26
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/Text.splitText
|
|
12
27
|
def split(offset)
|
|
13
|
-
`#@native.splitText(offset)`
|
|
28
|
+
DOM(`#@native.splitText(offset)`)
|
|
14
29
|
end
|
|
15
30
|
|
|
16
31
|
def inspect
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
module Browser
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# An {EventSource} allows you to receive events from a server in real-time,
|
|
4
|
+
# similar to long-polling but not exactly.
|
|
5
|
+
#
|
|
6
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/EventSource
|
|
4
7
|
class EventSource
|
|
5
8
|
def self.supported?
|
|
6
|
-
|
|
9
|
+
Browser.supports? :EventSource
|
|
7
10
|
end
|
|
8
11
|
|
|
9
12
|
include Native
|
data/opal/browser/history.rb
CHANGED
|
@@ -2,50 +2,86 @@ require 'browser/location'
|
|
|
2
2
|
|
|
3
3
|
module Browser
|
|
4
4
|
|
|
5
|
+
# {History} allows manipulation of the session history.
|
|
6
|
+
#
|
|
7
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/History
|
|
5
8
|
class History
|
|
9
|
+
# Check if HTML5 history is supported.
|
|
10
|
+
def self.supported?
|
|
11
|
+
Browser.supports? 'History'
|
|
12
|
+
end
|
|
13
|
+
|
|
6
14
|
include Native
|
|
7
15
|
|
|
16
|
+
# @!attribute [r] length
|
|
17
|
+
# @return [Integer] how many items are in the history
|
|
8
18
|
alias_native :length
|
|
9
19
|
|
|
20
|
+
# Go back in the history.
|
|
21
|
+
#
|
|
22
|
+
# @param number [Integer] how many items to go back
|
|
10
23
|
def back(number = 1)
|
|
11
24
|
`#@native.go(-number)`
|
|
12
|
-
|
|
13
|
-
self
|
|
14
25
|
end
|
|
15
26
|
|
|
27
|
+
# Go forward in the history.
|
|
28
|
+
#
|
|
29
|
+
# @param number [Integer] how many items to go forward
|
|
16
30
|
def forward(number = 1)
|
|
17
31
|
`#@native.go(number)`
|
|
18
|
-
|
|
19
|
-
self
|
|
20
32
|
end
|
|
21
33
|
|
|
22
|
-
|
|
34
|
+
# Push an item in the history.
|
|
35
|
+
#
|
|
36
|
+
# @param item [String] the item to push in the history
|
|
37
|
+
# @param data [Object] additional state to push
|
|
38
|
+
def push(item, data = nil)
|
|
23
39
|
data = `null` if data.nil?
|
|
24
40
|
|
|
25
|
-
`#@native.pushState(data, null,
|
|
26
|
-
|
|
27
|
-
self
|
|
41
|
+
`#@native.pushState(data, null, item)`
|
|
28
42
|
end
|
|
29
43
|
|
|
30
|
-
|
|
44
|
+
# Replace the current history item with another.
|
|
45
|
+
#
|
|
46
|
+
# @param item [String] the item to replace with
|
|
47
|
+
# @param data [Object] additional state to replace
|
|
48
|
+
def replace(item, data = nil)
|
|
31
49
|
data = `null` if data.nil?
|
|
32
50
|
|
|
33
|
-
`#@native.replaceState(data, null,
|
|
51
|
+
`#@native.replaceState(data, null, item)`
|
|
34
52
|
end
|
|
35
53
|
|
|
54
|
+
# @!attribute [r] current
|
|
55
|
+
# @return [String] the current item
|
|
36
56
|
def current
|
|
37
57
|
$window.location.path
|
|
38
58
|
end
|
|
39
59
|
|
|
40
|
-
|
|
41
|
-
|
|
60
|
+
# @!attribute [r] state
|
|
61
|
+
# @return [Object] the current state
|
|
62
|
+
if Browser.supports? 'History.state'
|
|
63
|
+
def state
|
|
64
|
+
%x{
|
|
65
|
+
var state = #@native.state;
|
|
66
|
+
|
|
67
|
+
if (state == null) {
|
|
68
|
+
return nil;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
return state;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
else
|
|
76
|
+
def state
|
|
77
|
+
raise NotImplementedError, 'history state unsupported'
|
|
78
|
+
end
|
|
42
79
|
end
|
|
43
80
|
end
|
|
44
81
|
|
|
45
82
|
class Window
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
# @return [History]
|
|
83
|
+
# @!attribute [r] history
|
|
84
|
+
# @return [History] the history for this window
|
|
49
85
|
def history
|
|
50
86
|
History.new(`#@native.history`) if `#@native.history`
|
|
51
87
|
end
|
data/opal/browser/http.rb
CHANGED
|
@@ -4,17 +4,21 @@ require 'browser/http/binary'
|
|
|
4
4
|
require 'browser/http/headers'
|
|
5
5
|
require 'browser/http/request'
|
|
6
6
|
require 'browser/http/response'
|
|
7
|
-
require 'browser/http/compatibility'
|
|
8
7
|
|
|
9
8
|
module Browser
|
|
10
9
|
|
|
11
10
|
module HTTP
|
|
11
|
+
def self.supported?
|
|
12
|
+
Browser.supports?('XHR') || Browser.supports?('ActiveXObject')
|
|
13
|
+
end
|
|
14
|
+
|
|
12
15
|
# Send an asynchronous request.
|
|
13
16
|
#
|
|
14
17
|
# @param method [Symbol] the HTTP method to use
|
|
15
18
|
# @param url [String] the URL to request
|
|
16
19
|
# @param data [String, Hash] the data to send
|
|
17
|
-
#
|
|
20
|
+
#
|
|
21
|
+
# @return [Promise] a promise that will be resolved with the response
|
|
18
22
|
def self.send(method, url, data = nil, &block)
|
|
19
23
|
Promise.new.tap {|promise|
|
|
20
24
|
Request.new(&block).tap {|req|
|
|
@@ -32,7 +36,8 @@ module HTTP
|
|
|
32
36
|
# Send an asynchronous GET request.
|
|
33
37
|
#
|
|
34
38
|
# @param url [String] the URL to request
|
|
35
|
-
#
|
|
39
|
+
#
|
|
40
|
+
# @return [Promise] a promise that will be resolved with the response
|
|
36
41
|
def self.get(url, &block)
|
|
37
42
|
send(:get, url, &block)
|
|
38
43
|
end
|
|
@@ -40,7 +45,8 @@ module HTTP
|
|
|
40
45
|
# Send an asynchronous HEAD request.
|
|
41
46
|
#
|
|
42
47
|
# @param url [String] the URL to request
|
|
43
|
-
#
|
|
48
|
+
#
|
|
49
|
+
# @return [Promise] a promise that will be resolved with the response
|
|
44
50
|
def self.head(url, &block)
|
|
45
51
|
send(:head, url, &block)
|
|
46
52
|
end
|
|
@@ -49,7 +55,8 @@ module HTTP
|
|
|
49
55
|
#
|
|
50
56
|
# @param url [String] the URL to request
|
|
51
57
|
# @param data [String, Hash] the data to send
|
|
52
|
-
#
|
|
58
|
+
#
|
|
59
|
+
# @return [Promise] a promise that will be resolved with the response
|
|
53
60
|
def self.post(url, data = nil, &block)
|
|
54
61
|
send(:post, url, data, &block)
|
|
55
62
|
end
|
|
@@ -58,7 +65,8 @@ module HTTP
|
|
|
58
65
|
#
|
|
59
66
|
# @param url [String] the URL to request
|
|
60
67
|
# @param data [String, Hash] the data to send
|
|
61
|
-
#
|
|
68
|
+
#
|
|
69
|
+
# @return [Promise] a promise that will be resolved with the response
|
|
62
70
|
def self.put(url, data = nil, &block)
|
|
63
71
|
send(:put, url, data, &block)
|
|
64
72
|
end
|
|
@@ -67,7 +75,8 @@ module HTTP
|
|
|
67
75
|
#
|
|
68
76
|
# @param url [String] the URL to request
|
|
69
77
|
# @param data [String, Hash] the data to send
|
|
70
|
-
#
|
|
78
|
+
#
|
|
79
|
+
# @return [Promise] a promise that will be resolved with the response
|
|
71
80
|
def self.delete(url, data = nil, &block)
|
|
72
81
|
send(:delete, url, data, &block)
|
|
73
82
|
end
|
|
@@ -77,6 +86,7 @@ module HTTP
|
|
|
77
86
|
# @param method [Symbol] the HTTP method to use
|
|
78
87
|
# @param url [String] the URL to request
|
|
79
88
|
# @param data [String, Hash] the data to send
|
|
89
|
+
#
|
|
80
90
|
# @return [Response] the response
|
|
81
91
|
def self.send!(method, url, data = nil, &block)
|
|
82
92
|
Request.new(&block).open(method, url, false).send(data)
|
|
@@ -85,6 +95,7 @@ module HTTP
|
|
|
85
95
|
# Send a synchronous GET request.
|
|
86
96
|
#
|
|
87
97
|
# @param url [String] the URL to request
|
|
98
|
+
#
|
|
88
99
|
# @return [Response] the response
|
|
89
100
|
def self.get!(url, &block)
|
|
90
101
|
send!(:get, url, &block)
|
|
@@ -93,6 +104,7 @@ module HTTP
|
|
|
93
104
|
# Send a synchronous HEAD request.
|
|
94
105
|
#
|
|
95
106
|
# @param url [String] the URL to request
|
|
107
|
+
#
|
|
96
108
|
# @return [Response] the response
|
|
97
109
|
def self.head!(url, &block)
|
|
98
110
|
send!(:head, url, &block)
|
|
@@ -102,6 +114,7 @@ module HTTP
|
|
|
102
114
|
#
|
|
103
115
|
# @param url [String] the URL to request
|
|
104
116
|
# @param data [String, Hash] the data to send
|
|
117
|
+
#
|
|
105
118
|
# @return [Response] the response
|
|
106
119
|
def self.post!(url, data = nil, &block)
|
|
107
120
|
send!(:post, url, data, &block)
|
|
@@ -111,6 +124,7 @@ module HTTP
|
|
|
111
124
|
#
|
|
112
125
|
# @param url [String] the URL to request
|
|
113
126
|
# @param data [String, Hash] the data to send
|
|
127
|
+
#
|
|
114
128
|
# @return [Response] the response
|
|
115
129
|
def self.put!(url, data = nil, &block)
|
|
116
130
|
send!(:put, url, data, &block)
|
|
@@ -120,6 +134,7 @@ module HTTP
|
|
|
120
134
|
#
|
|
121
135
|
# @param url [String] the URL to request
|
|
122
136
|
# @param data [String, Hash] the data to send
|
|
137
|
+
#
|
|
123
138
|
# @return [Response] the response
|
|
124
139
|
def self.delete!(url, data = nil, &block)
|
|
125
140
|
send!(:delete, url, data, &block)
|
|
@@ -8,7 +8,6 @@ class Request
|
|
|
8
8
|
# @param method [Symbol] the HTTP method to use
|
|
9
9
|
# @param url [String, #to_s] the URL to request
|
|
10
10
|
# @param parameters [String, Hash] the parameters to send
|
|
11
|
-
#
|
|
12
11
|
def self.open(method, url, parameters = nil, &block)
|
|
13
12
|
request = new(&block)
|
|
14
13
|
request.open(method, url)
|
|
@@ -44,11 +43,13 @@ class Request
|
|
|
44
43
|
def initialize(&block)
|
|
45
44
|
super(transport)
|
|
46
45
|
|
|
46
|
+
@parameters = {}
|
|
47
|
+
@query = {}
|
|
47
48
|
@headers = Headers[DEFAULT_HEADERS]
|
|
48
49
|
@method = :get
|
|
49
50
|
@asynchronous = true
|
|
50
51
|
@binary = false
|
|
51
|
-
@cacheable
|
|
52
|
+
@cacheable = true
|
|
52
53
|
@opened = false
|
|
53
54
|
@sent = false
|
|
54
55
|
@completed = false
|
|
@@ -61,8 +62,20 @@ class Request
|
|
|
61
62
|
end if block
|
|
62
63
|
end
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
# @!method transport
|
|
66
|
+
# @private
|
|
67
|
+
if Browser.supports? :XHR
|
|
68
|
+
def transport
|
|
69
|
+
`new XMLHttpRequest()`
|
|
70
|
+
end
|
|
71
|
+
elsif Browser.supports? :ActiveX
|
|
72
|
+
def transport
|
|
73
|
+
`new ActiveXObject("MSXML2.XMLHTTP.3.0")`
|
|
74
|
+
end
|
|
75
|
+
else
|
|
76
|
+
def transport
|
|
77
|
+
raise NotImplementedError
|
|
78
|
+
end
|
|
66
79
|
end
|
|
67
80
|
|
|
68
81
|
# Check if the request has been opened.
|
|
@@ -183,11 +196,18 @@ class Request
|
|
|
183
196
|
#
|
|
184
197
|
# @param hash [Hash] the parameters
|
|
185
198
|
#
|
|
186
|
-
# @return [
|
|
187
|
-
def parameters(hash)
|
|
188
|
-
@parameters = hash
|
|
199
|
+
# @return [Hash]
|
|
200
|
+
def parameters(hash = nil)
|
|
201
|
+
hash ? @parameters = hash : @parameters
|
|
202
|
+
end
|
|
189
203
|
|
|
190
|
-
|
|
204
|
+
# Set the URI query.
|
|
205
|
+
#
|
|
206
|
+
# @param hash [Hash] the query
|
|
207
|
+
#
|
|
208
|
+
# @return [Hash]
|
|
209
|
+
def query(hash = nil)
|
|
210
|
+
hash ? @query = hash : @query
|
|
191
211
|
end
|
|
192
212
|
|
|
193
213
|
# Register an event on the request.
|
|
@@ -223,7 +243,17 @@ class Request
|
|
|
223
243
|
url = @url
|
|
224
244
|
|
|
225
245
|
unless cacheable?
|
|
226
|
-
|
|
246
|
+
@query[:_] = rand
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
unless @query.empty?
|
|
250
|
+
if url.include???
|
|
251
|
+
url += ?&
|
|
252
|
+
else
|
|
253
|
+
url += ??
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
url += @query.encode_uri
|
|
227
257
|
end
|
|
228
258
|
|
|
229
259
|
`#@native.open(#{@method.to_s.upcase}, #{url.to_s}, #{@asynchronous}, #{@user.to_n}, #{@password.to_n})`
|
|
@@ -279,7 +309,7 @@ class Request
|
|
|
279
309
|
|
|
280
310
|
if String === parameters
|
|
281
311
|
data = parameters
|
|
282
|
-
elsif Hash === parameters
|
|
312
|
+
elsif Hash === parameters && !parameters.empty?
|
|
283
313
|
data = parameters.map {|vals|
|
|
284
314
|
vals.map(&:encode_uri_component).join(?=)
|
|
285
315
|
}.join(?&)
|
data/opal/browser/immediate.rb
CHANGED
|
@@ -1,9 +1,30 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'promise'
|
|
2
2
|
|
|
3
3
|
module Browser
|
|
4
4
|
|
|
5
|
-
#
|
|
5
|
+
# Class to easily create and dispatch an immediate call.
|
|
6
|
+
#
|
|
7
|
+
# Immediate calls are deferred function calls that happen as soon as they can
|
|
8
|
+
# be scheduled.
|
|
9
|
+
#
|
|
10
|
+
# Compatibility
|
|
11
|
+
# -------------
|
|
12
|
+
# The compatibility layer will try various implementations in the following
|
|
13
|
+
# order.
|
|
14
|
+
#
|
|
15
|
+
# + [setImmediate](https://developer.mozilla.org/en-US/docs/Web/API/Window.setImmediate)
|
|
16
|
+
# + [postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage)
|
|
17
|
+
# + [readystatechange](https://developer.mozilla.org/en-US/docs/Web/Reference/Events/readystatechange)
|
|
18
|
+
# + [setTimeout](https://developer.mozilla.org/en/docs/Web/API/window.setTimeout)
|
|
19
|
+
#
|
|
20
|
+
# The order has been chosen from best to worst for both performance and
|
|
21
|
+
# preemptiveness.
|
|
6
22
|
class Immediate
|
|
23
|
+
# Create an immediate for the given function which will be called with the
|
|
24
|
+
# arguments and block.
|
|
25
|
+
#
|
|
26
|
+
# @param func [Proc] the function to call
|
|
27
|
+
# @param args [Array] the arguments to call it with
|
|
7
28
|
def initialize(func, args, &block)
|
|
8
29
|
@aborted = false
|
|
9
30
|
@function = func
|
|
@@ -11,14 +32,89 @@ class Immediate
|
|
|
11
32
|
@block = block
|
|
12
33
|
end
|
|
13
34
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
end unless method_defined? :dispatch
|
|
35
|
+
# @!method dispatch
|
|
36
|
+
# Dispatch the immediate.
|
|
17
37
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
end unless method_defined? :prevent
|
|
38
|
+
# @!method prevent
|
|
39
|
+
# Prevent the immediate from being called once scheduled.
|
|
21
40
|
|
|
41
|
+
if Browser.supports? 'Immediate'
|
|
42
|
+
def dispatch
|
|
43
|
+
@id = `window.setImmediate(function() {
|
|
44
|
+
#{@function.call(*@arguments, &@block)};
|
|
45
|
+
})`
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def prevent
|
|
49
|
+
`window.clearImmediate(#@id)`
|
|
50
|
+
end
|
|
51
|
+
elsif Browser.supports? 'Immediate (Internet Explorer)'
|
|
52
|
+
def dispatch
|
|
53
|
+
@id = `window.msSetImmediate(function() {
|
|
54
|
+
#{@function.call(*@arguments, &@block)};
|
|
55
|
+
})`
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def prevent
|
|
59
|
+
`window.msClearImmediate(#@id)`
|
|
60
|
+
end
|
|
61
|
+
elsif Browser.supports? 'Window.send'
|
|
62
|
+
# @private
|
|
63
|
+
@@tasks = {}
|
|
64
|
+
|
|
65
|
+
# @private
|
|
66
|
+
@@prefix = "opal.browser.immediate.#{rand(1_000_000)}."
|
|
67
|
+
|
|
68
|
+
$window.on :message do |e|
|
|
69
|
+
if String === e.data && e.data.start_with?(@@prefix)
|
|
70
|
+
if task = @@tasks.delete(e.data[@@prefix.length .. -1])
|
|
71
|
+
task[0].call(*task[1], &task[2])
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def dispatch
|
|
77
|
+
@id = rand(1_000_000).to_s
|
|
78
|
+
@@tasks[@id] = [@function, @arguments, @block]
|
|
79
|
+
|
|
80
|
+
$window.send! "#{@@prefix}#{@id}"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def prevent
|
|
84
|
+
@@tasks.delete(@id)
|
|
85
|
+
end
|
|
86
|
+
elsif Browser.supports? 'Event.readystatechange'
|
|
87
|
+
def dispatch
|
|
88
|
+
%x{
|
|
89
|
+
var script = document.createElement("script");
|
|
90
|
+
|
|
91
|
+
script.onreadystatechange = function() {
|
|
92
|
+
if (!#{aborted?}) {
|
|
93
|
+
#{@function.call(*@arguments, &@block)};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
script.onreadystatechange = null;
|
|
97
|
+
script.parentNode.removeChild(script);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
document.documentElement.appendChild(script);
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def prevent; end
|
|
105
|
+
else
|
|
106
|
+
def dispatch
|
|
107
|
+
@id = `window.setTimeout(function() {
|
|
108
|
+
#{@function.call(*@arguments, &@block)};
|
|
109
|
+
}, 0)`
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def prevent
|
|
113
|
+
`window.clearTimeout(#@id)`
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Abort the immediate.
|
|
22
118
|
def abort
|
|
23
119
|
return if aborted?
|
|
24
120
|
|
|
@@ -28,6 +124,7 @@ class Immediate
|
|
|
28
124
|
self
|
|
29
125
|
end
|
|
30
126
|
|
|
127
|
+
# Check if the immediate has been aborted.
|
|
31
128
|
def aborted?
|
|
32
129
|
@aborted
|
|
33
130
|
end
|
|
@@ -36,8 +133,25 @@ end
|
|
|
36
133
|
end
|
|
37
134
|
|
|
38
135
|
class Proc
|
|
39
|
-
#
|
|
136
|
+
# (see Immediate.new)
|
|
40
137
|
def defer(*args, &block)
|
|
41
138
|
Browser::Immediate.new(self, args, &block).tap(&:dispatch)
|
|
42
139
|
end
|
|
43
140
|
end
|
|
141
|
+
|
|
142
|
+
class Promise
|
|
143
|
+
# Create a promise which will be resolved with the result of the immediate.
|
|
144
|
+
#
|
|
145
|
+
# @param args [Array] the arguments the block will be called with
|
|
146
|
+
def self.defer(*args, &block)
|
|
147
|
+
new.tap {|promise|
|
|
148
|
+
proc {
|
|
149
|
+
begin
|
|
150
|
+
promise.resolve(block.call(*args))
|
|
151
|
+
rescue Exception => e
|
|
152
|
+
promise.reject(e)
|
|
153
|
+
end
|
|
154
|
+
}.defer
|
|
155
|
+
}
|
|
156
|
+
end
|
|
157
|
+
end
|