flok 0.0.102 → 0.0.103
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitmodules +3 -0
- data/app/drivers/chrome/pipe.rb +66 -51
- data/app/drivers/chrome/src/controller.js +20 -1
- data/app/drivers/chrome/src/hook.js +10 -12
- data/app/drivers/chrome/src/net.js +4 -4
- data/app/drivers/chrome/src/sockio.js +2 -2
- data/app/drivers/chrome/src/ui.js +18 -15
- data/app/kern/mod/event.js +3 -1
- data/app/kern/mod/hook.js +13 -1
- data/app/kern/mod/ui.js +71 -0
- data/docs/controllers.md +14 -0
- data/docs/dispatch.md +4 -2
- data/docs/kernel_api.md +1 -0
- data/docs/kernel_handbook/find_view.md +34 -0
- data/docs/kernel_handbook/hooks.md +12 -1
- data/docs/mod/controller.md +5 -2
- data/docs/mod/hook.md +4 -3
- data/docs/mod/persist.md +1 -1
- data/docs/mod/ui.md +1 -0
- data/docs/user_handbook/hooks.md +38 -14
- data/flok.gemspec +2 -0
- data/lib/flok/user_compiler.rb +18 -2
- data/lib/flok/user_compiler_templates/ctable.js.erb +1 -0
- data/lib/flok/user_hook_generators/goto.rb +32 -4
- data/lib/flok/version.rb +1 -1
- data/spec/env/iface.rb +38 -0
- data/spec/env/kern.rb +4 -0
- data/spec/iface/driver/controller_spec.rb +25 -6
- data/spec/iface/driver/dispatch_spec.rb +7 -0
- data/spec/iface/driver/hook_spec.rb +83 -7
- data/spec/iface/driver/net_spec.rb +50 -41
- data/spec/iface/driver/persist_spec.rb +47 -4
- data/spec/iface/driver/ping_spec.rb +1 -1
- data/spec/iface/driver/rtc_spec.rb +2 -2
- data/spec/iface/driver/sockio_spec.rb +4 -3
- data/spec/iface/driver/timer_spec.rb +20 -0
- data/spec/iface/driver/ui_spec.rb +27 -4
- data/spec/kern/assets/find_view/controller0.rb +24 -0
- data/spec/kern/assets/find_view/controller1.rb +35 -0
- data/spec/kern/assets/find_view/controller1a.rb +37 -0
- data/spec/kern/assets/find_view/controller2.rb +23 -0
- data/spec/kern/assets/find_view/controller3.rb +38 -0
- data/spec/kern/assets/find_view/controller4.rb +38 -0
- data/spec/kern/assets/find_view/controller5.rb +52 -0
- data/spec/kern/assets/find_view/controller6.rb +37 -0
- data/spec/kern/assets/find_view/controller7.rb +37 -0
- data/spec/kern/assets/find_view/controller8.rb +53 -0
- data/spec/kern/assets/find_view/controller9.rb +67 -0
- data/spec/kern/assets/hook_entry_points/controller0.rb +13 -1
- data/spec/kern/assets/push_count.rb +42 -0
- data/spec/kern/controller_spec.rb +34 -0
- data/spec/kern/find_view_spec.rb +269 -0
- data/spec/kern/hook_entry_points_and_manifest_spec.rb +60 -0
- data/spec/kern/hook_user_generators_spec.rb +100 -0
- data/spec/lib/helpers.rb +1 -2
- metadata +58 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d3dd5275337abe10712fa3347a698c60819ff78
|
4
|
+
data.tar.gz: e126f18d24e069176e485f6db5327c407dafad71
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: baaa0fb3c2b68b3460e892d0f8d1c084e2d20eea45baaf29ff1ed8232bacd67cbd1aa0362a6fc725fd57be77519593c56021042c48d17a6b22c3b1d52ae2f1e3
|
7
|
+
data.tar.gz: ee1f06e6d0210adf94dbb9a7780945a4f9a9c37a1b39ac15d1b85512c2cecb678fdb064f9248da5406e49ccf9f5071383e32b7c60ceda860d86705cd93adc42e
|
data/.gitmodules
ADDED
data/app/drivers/chrome/pipe.rb
CHANGED
@@ -15,69 +15,84 @@ class InteractiveServer
|
|
15
15
|
|
16
16
|
#Will take over any remaining IO
|
17
17
|
def begin_pipe
|
18
|
-
|
19
|
-
path = tmp.path
|
20
|
-
tmp.close!
|
21
|
-
File.write path, @app_js
|
18
|
+
puts "LOADED"
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
20
|
+
_begin_pipe
|
21
|
+
end
|
22
|
+
|
23
|
+
def _begin_pipe
|
24
|
+
catch(:is_restarting) do
|
25
|
+
tmp = Tempfile.new(SecureRandom.hex)
|
26
|
+
path = tmp.path
|
27
|
+
tmp.close!
|
28
|
+
File.write path, @app_js
|
29
|
+
|
30
|
+
p = Open3.popen3 "boojs #{path}" do |inp, out, err, t|
|
31
|
+
pid = t[:pid]
|
32
|
+
begin
|
33
|
+
loop do
|
34
|
+
results = select([out, err, STDIN], [])
|
35
|
+
if results[0].include? err
|
36
|
+
err_msg = err.readline
|
37
|
+
$stderr.puts err_msg
|
38
|
+
#exit 1 unless err_msg =~ /[debug]/
|
39
|
+
end
|
40
|
+
|
41
|
+
if results[0].include? STDIN
|
42
|
+
begin
|
43
|
+
q = gets.strip
|
44
|
+
|
45
|
+
if q == "HARD_RESTART"
|
46
|
+
throw :is_restarting
|
47
|
+
elsif q == "RESTART"
|
48
|
+
inp.puts "$__RESTART__"
|
33
49
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
50
|
+
begin
|
51
|
+
#Wait for restart to respond 'ok'
|
52
|
+
Timeout::timeout(10) do
|
53
|
+
restart_res = out.readline
|
54
|
+
raise "Restart of phantomjs did not return '__RESTART_OK__' like expected, returned: #{restart_res.inspect}" unless restart_res == "$__RESTART_OK__\n"
|
39
55
|
|
40
|
-
|
41
|
-
|
42
|
-
Timeout::
|
43
|
-
|
44
|
-
|
56
|
+
puts "RESTART OK"
|
57
|
+
end
|
58
|
+
rescue Timeout::Error
|
59
|
+
raise "Restart of boojs did not happen within 5 seconds"
|
60
|
+
rescue EOFError
|
61
|
+
#Sleep for a second to let the error pipe fill up from boojs, this error
|
62
|
+
#will then be displayed and then we will crash
|
63
|
+
sleep 3
|
64
|
+
$stderr.puts err.read
|
65
|
+
raise "boojs encountered an error"
|
45
66
|
end
|
46
|
-
rescue Timeout::Error
|
47
|
-
raise "Restart of boojs did not happen within 5 seconds"
|
48
|
-
rescue EOFError
|
49
|
-
#Sleep for a second to let the error pipe fill up from boojs, this error
|
50
|
-
#will then be displayed and then we will crash
|
51
|
-
sleep 3
|
52
|
-
$stderr.puts err.read
|
53
|
-
raise "boojs encountered an error"
|
54
|
-
end
|
55
67
|
|
56
|
-
|
57
|
-
|
58
|
-
|
68
|
+
else
|
69
|
+
inp.puts "if_dispatch(JSON.parse('#{q}'))"
|
70
|
+
end
|
71
|
+
rescue Errno::EIO
|
72
|
+
#Can't say anything here, we don't have a pipe
|
73
|
+
exit 1
|
74
|
+
rescue NoMethodError
|
75
|
+
exit 1
|
59
76
|
end
|
60
|
-
rescue Errno::EIO
|
61
|
-
#Can't say anything here, we don't have a pipe
|
62
|
-
exit 1
|
63
|
-
rescue NoMethodError
|
64
|
-
exit 1
|
65
77
|
end
|
66
|
-
end
|
67
78
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
79
|
+
if results[0].include? out
|
80
|
+
res = out.readline
|
81
|
+
$stdout.puts res
|
82
|
+
$stdout.flush
|
83
|
+
end
|
84
|
+
end
|
85
|
+
ensure
|
86
|
+
begin
|
87
|
+
Process.kill :INT, pid
|
88
|
+
rescue Errno::ESRCH
|
72
89
|
end
|
73
|
-
end
|
74
|
-
ensure
|
75
|
-
begin
|
76
|
-
Process.kill :INT, pid
|
77
|
-
rescue Errno::ESRCH
|
78
90
|
end
|
79
91
|
end
|
80
92
|
end
|
93
|
+
|
94
|
+
puts "RESTART OK"
|
95
|
+
_begin_pipe
|
81
96
|
end
|
82
97
|
|
83
98
|
#JS Functions#####################################################
|
@@ -159,9 +159,28 @@ function if_spec_controller_init() {
|
|
159
159
|
}
|
160
160
|
}
|
161
161
|
|
162
|
+
var TestControllerContext = function() {
|
163
|
+
this.base = FlokController; this.base(); self = this;
|
164
|
+
|
165
|
+
this.init = function() {
|
166
|
+
self.send("context", self.context)
|
167
|
+
}
|
168
|
+
|
169
|
+
self.action = function(from, to) {
|
170
|
+
self.send("action_rcv", {from: from, to:to});
|
171
|
+
}
|
172
|
+
|
173
|
+
self.event = function(name, info) {
|
174
|
+
self.send("custom_rcv", {name:name, info:info})
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
|
162
179
|
//Register the new controller
|
163
180
|
$(document).ready(function() {
|
164
|
-
regController("
|
181
|
+
regController("spec_blank", TestController);
|
182
|
+
regController("spec_one_spot", TestController);
|
183
|
+
regController("spec_blank_sends_context", TestControllerContext);
|
165
184
|
});
|
166
185
|
}
|
167
186
|
|
@@ -1,23 +1,11 @@
|
|
1
1
|
//Driver side interface
|
2
2
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
3
3
|
function if_hook_event(name, info) {
|
4
|
-
<% if @debug %>
|
5
|
-
if_hook_spec_dump_rcvd_events_log.push({name: name, info: info});
|
6
|
-
<% end %>
|
7
|
-
|
8
4
|
//Call the appropriate registered handler
|
9
5
|
if (hookEventHandlers[name] !== undefined) {
|
10
6
|
hookEventHandlers[name](info);
|
11
7
|
}
|
12
8
|
}
|
13
|
-
|
14
|
-
<% if @debug %>
|
15
|
-
//Track all events sent to if_hook_event
|
16
|
-
var if_hook_spec_dump_rcvd_events_log = []
|
17
|
-
function if_hook_spec_dump_rcvd_events() {
|
18
|
-
int_dispatch([1, "if_hook_spec_dump_rcvd_events_res", if_hook_spec_dump_rcvd_events_log]);
|
19
|
-
}
|
20
|
-
<% end %>
|
21
9
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
22
10
|
|
23
11
|
//User helpers
|
@@ -27,3 +15,13 @@ function onHookEvent(eventName, handler) {
|
|
27
15
|
hookEventHandlers[eventName] = handler;
|
28
16
|
}
|
29
17
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
18
|
+
|
19
|
+
<% if @debug %>
|
20
|
+
onHookEvent("test", function(info) {
|
21
|
+
int_dispatch([1, "hook_dump_res", {name: "test", info: info}]);
|
22
|
+
});
|
23
|
+
|
24
|
+
onHookEvent("test2", function(info) {
|
25
|
+
int_dispatch([1, "hook_dump_res", {name: "test2", info: info}]);
|
26
|
+
});
|
27
|
+
<% end %>
|
@@ -11,8 +11,8 @@ if_net_req = function(verb, url, params, tp_base) {
|
|
11
11
|
success: function(data) {
|
12
12
|
int_dispatch([3, "int_net_cb", tp_base, true, data]);
|
13
13
|
},
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
error: function(xhr, textStatus, err) {
|
15
|
+
int_dispatch([3, "int_net_cb", tp_base, false, textStatus]);
|
16
|
+
}
|
17
|
+
})
|
18
18
|
}
|
@@ -17,7 +17,7 @@ function if_sockio_fwd(sp, event_name, bp) {
|
|
17
17
|
});
|
18
18
|
} else {
|
19
19
|
<% if @debug %>
|
20
|
-
console.error("Couldnt fwd sockio with sp: " + sp + " (It
|
20
|
+
console.error("Couldnt fwd sockio with sp: " + sp + " (It does not exist)");
|
21
21
|
<% end %>
|
22
22
|
}
|
23
23
|
}
|
@@ -30,7 +30,7 @@ function if_sockio_send(sp, event_name, info) {
|
|
30
30
|
socket.emit(event_name, info);
|
31
31
|
} else {
|
32
32
|
<% if @debug %>
|
33
|
-
console.error("Couldnt fwd sockio with sp: " + sp + " (It
|
33
|
+
console.error("Couldnt fwd sockio with sp: " + sp + " (It does not exist)");
|
34
34
|
<% end %>
|
35
35
|
}
|
36
36
|
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
//Create a new surface based on a prototype name and information.
|
2
2
|
//Store that view in our own pointer table that uses selectors
|
3
|
+
|
3
4
|
//Both spots and views
|
4
5
|
if_ui_tp_to_selector = {};
|
5
6
|
|
@@ -113,21 +114,23 @@ function if_free_view(vp) {
|
|
113
114
|
//Spec related////////////////////////////////////////////////
|
114
115
|
function if_ui_spec_init() {
|
115
116
|
//Set the body HTML
|
116
|
-
var body_html = "
|
117
|
-
<div id='root'></div>
|
118
|
-
|
119
|
-
<div id='prototypes' style='display: none'>
|
120
|
-
<div class='view' data-name='spec_blank'>
|
121
|
-
</div>
|
122
|
-
<div class='view' data-name='
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
117
|
+
var body_html = " \
|
118
|
+
<div id='root'></div> \
|
119
|
+
\
|
120
|
+
<div id='prototypes' style='display: none'> \
|
121
|
+
<div class='view' data-name='spec_blank'> \
|
122
|
+
</div> \
|
123
|
+
<div class='view' data-name='spec_blank_sends_context'> \
|
124
|
+
</div> \
|
125
|
+
<div class='view' data-name='spec_one_spot'> \
|
126
|
+
<div class='spot' data-name='content'></div> \
|
127
|
+
</div> \
|
128
|
+
<div class='view' data-name='spec_two_spot'> \
|
129
|
+
<div class='spot' data-name='a'></div> \
|
130
|
+
<div class='spot' data-name='b'></div> \
|
131
|
+
</div> \
|
132
|
+
</div> \
|
133
|
+
\
|
131
134
|
"
|
132
135
|
$("body").html(body_html);
|
133
136
|
}
|
data/app/kern/mod/event.js
CHANGED
@@ -6,7 +6,9 @@ edefer_q = [];
|
|
6
6
|
|
7
7
|
function int_event(ep, event_name, info) {
|
8
8
|
<% if @debug %>
|
9
|
-
if (ep
|
9
|
+
if (ep) {
|
10
|
+
if (ep.constructor !== String && ep.constructor !== Number) { throw "int_event was given either something that wasn't a string or number for ep: '" + (ep.constructor) + "' and the value was: '" + ep + "'"};
|
11
|
+
}
|
10
12
|
<% end %>
|
11
13
|
|
12
14
|
var f = evt[ep];
|
data/app/kern/mod/hook.js
CHANGED
@@ -1 +1,13 @@
|
|
1
|
-
//
|
1
|
+
//goto hook generator expects this callback to be received usually for completion
|
2
|
+
function hook_goto_completion_cb(ep, ename, info) {
|
3
|
+
var views_to_free_id = ep;
|
4
|
+
var our_views_to_free = views_to_free[ep];
|
5
|
+
|
6
|
+
delete views_to_free[ep];
|
7
|
+
dereg_evt(ep);
|
8
|
+
|
9
|
+
for (var key in our_views_to_free) {
|
10
|
+
var bp = our_views_to_free[key];
|
11
|
+
main_q.push([1, "if_free_view", bp]);
|
12
|
+
}
|
13
|
+
}
|
data/app/kern/mod/ui.js
CHANGED
@@ -1,2 +1,73 @@
|
|
1
1
|
function int_embed_surface(sp) {
|
2
2
|
}
|
3
|
+
|
4
|
+
function find_view(bp, spider) {
|
5
|
+
var res = {};
|
6
|
+
_find_view(bp, spider, res);
|
7
|
+
|
8
|
+
return res;
|
9
|
+
}
|
10
|
+
|
11
|
+
function _find_view(bp, spider, shared) {
|
12
|
+
var leaf = spider["__leaf__"];
|
13
|
+
if (leaf) {
|
14
|
+
shared[leaf] = bp
|
15
|
+
}
|
16
|
+
|
17
|
+
var ctable = tel_deref(bp);
|
18
|
+
var embeds = ctable.embeds;
|
19
|
+
|
20
|
+
for (var x = 0; x < embeds.length; ++x) {
|
21
|
+
for (var i = 0; i < embeds[x].length; ++i) {
|
22
|
+
//Pull info about the entry (subview)
|
23
|
+
var entry_bp = embeds[x][i];
|
24
|
+
var entry_cinfo = tel_deref(entry_bp); // The sub controller's info
|
25
|
+
var entry_ctable = entry_cinfo.cte; // The sub controller's ctable static
|
26
|
+
var entry_name = entry_ctable.name; // The sub controller's name
|
27
|
+
|
28
|
+
//Direct match found
|
29
|
+
var direct_match = spider[entry_name];
|
30
|
+
var dot_match = spider["."];
|
31
|
+
var plus_match = spider["+"];
|
32
|
+
|
33
|
+
if (direct_match) {
|
34
|
+
_find_view(entry_bp, direct_match, shared);
|
35
|
+
}
|
36
|
+
|
37
|
+
if (dot_match) {
|
38
|
+
_find_view(entry_bp, dot_match, shared);
|
39
|
+
}
|
40
|
+
|
41
|
+
if (plus_match) {
|
42
|
+
_find_view(entry_bp, plus_match, shared);
|
43
|
+
var partial_plus = {
|
44
|
+
"+": plus_match
|
45
|
+
}
|
46
|
+
_find_view(entry_bp, partial_plus, shared);
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
////For all spots
|
52
|
+
//for (var x = 0; x < embeds.length; ++x) {
|
53
|
+
////Search
|
54
|
+
//for (var i = 0; i < embeds[x].length; ++i) {
|
55
|
+
////Lookup ctable for the embed
|
56
|
+
//var _ctable = tel_deref(embeds[x][i]);
|
57
|
+
|
58
|
+
////Get it's name
|
59
|
+
//var name = _ctable.cte.name;
|
60
|
+
|
61
|
+
////Does it match something in our spider?
|
62
|
+
//if (spider[_ctable.cte.name]) {
|
63
|
+
//output[spider[_ctable.cte.name].__leaf__] = embeds[x][i];
|
64
|
+
//} else if (spider["."]) {
|
65
|
+
//output[spider["."].__leaf__] = embeds[x][i];
|
66
|
+
//}
|
67
|
+
//}
|
68
|
+
//}
|
69
|
+
//return output;
|
70
|
+
}
|
71
|
+
|
72
|
+
//Used by the delayed free views typically for the GOTO hook specifically
|
73
|
+
var views_to_free = {};
|
data/docs/controllers.md
CHANGED
@@ -55,6 +55,20 @@ controller "tab_controller" do
|
|
55
55
|
}
|
56
56
|
end
|
57
57
|
|
58
|
+
#Navigation stacks often have multiple entry points, 'back' may differ
|
59
|
+
#in action depending on whether it is the highest in the stack, you
|
60
|
+
#may use the 'push_count' variable to get the current level of the
|
61
|
+
#hierarchy you are on
|
62
|
+
macro :my_stack_macro do
|
63
|
+
on "back_clicked", %{
|
64
|
+
//If the push_level is 0, then we cannot Pop
|
65
|
+
if (push_count === 0) {
|
66
|
+
Raise("back_clicked");
|
67
|
+
} else {
|
68
|
+
Pop();
|
69
|
+
}
|
70
|
+
}
|
71
|
+
end
|
58
72
|
|
59
73
|
#Optional
|
60
74
|
#Called after on_entry, but before any action is entered. This is a pseudo
|
data/docs/dispatch.md
CHANGED
@@ -14,14 +14,16 @@ There are various stages of message processing so it can be confusing as to what
|
|
14
14
|
1. The disptach mechanism, `int_dispatch`, is always called by the client synchronously, and the javascript core will always respond synchronously to `if_disptach`.
|
15
15
|
2. The client `if_dispatch` handler will then process the main queue on it's same synchronous thread and then dispatch, asynchronously, the remaining queues; the queues may either each dispatch messages asynchronously or synchronously w.r.t to the original queue. (out of order and parallel are supported)
|
16
16
|
|
17
|
-
Additionally, it is **never** ok to
|
18
|
-
`controller` systems rely on ordering.
|
17
|
+
Additionally, it is **never** ok to upgrade a synchronous request to an asynchronous request. Some functions, particularly the `vm` and
|
18
|
+
`controller` systems rely on ordering. Synchronous requests must be done in order and on a single thread; additionally, they can be UI requests which are typically handled on the main thread.
|
19
19
|
|
20
20
|
For example, if we dispatch on the `main` queue a disk read request, flok would expect that the disk read would block the javascript core and return execution as soon as the disk read completed. Flok would also presume that the disk read was done at the fastest
|
21
21
|
and highest priority of IO and CPU.
|
22
22
|
|
23
23
|
Flok would expect that same disk requets, dispatched on an asynhcronous queue, like `disk`, that the request would not execute on the same thread of execution and could execute out of order.
|
24
24
|
|
25
|
+
**To re-iterate, `main` is the only synchronous queue; the other queues may be asynchronous but must be dispatched asynchronously; (they may also be asynchronous in nature)**
|
26
|
+
|
25
27
|
##The standard Flok queues (resources) are defined with the labels:
|
26
28
|
0. `main` - User-interface displaying, etc.
|
27
29
|
1. `net` - Downloading, Uploading, Get requests, etc.
|
data/docs/kernel_api.md
CHANGED
@@ -38,6 +38,7 @@ instead.
|
|
38
38
|
* `_embed(vc_name, sp, context, event_gw)` - Embed a view controller in a surface-pointer. Following the rules of the ui device, embedded to a sp of
|
39
39
|
0 is the master root view. Returns base pointer. `event_gw` is a pointer to a `vc`. If it is null, then any events coming in will not be sent to
|
40
40
|
somewhere else if they do not match any 'on' for the current action.
|
41
|
+
* `find_view(bp, spider_payload)` - Traverses the hierarchy within some controller (`bp`) and returns the named entries. See [find_view_specifics](./kernel_handbook/find_view.md) for how this works.
|
41
42
|
|
42
43
|
##Timers
|
43
44
|
* See [./callout.md](Callout) for how to register a timer
|