alaska 1.0.4
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 +7 -0
- data/alaska.js +52 -0
- data/lib/alaska/context.rb +72 -0
- data/lib/alaska/runtime.rb +100 -0
- metadata +91 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 838fe0565db0f27a2c6f91f1cc16af4104401a05
|
4
|
+
data.tar.gz: cbc675b45795d1fd7145066f0fe711c454cc71d6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b7ac32056cfafd5da0fa134eadf37137ec5172c257566863e70aea3146f84869beb0ece8f1bdc5effec520c3d6a5df10703c5bb00812a925d2c5fa817dca78d7
|
7
|
+
data.tar.gz: caf187b1da186e80c3cc86498746a49ac749d07de9ba0d8ee305148158753328c2e3b35c451914a9d80677866c4e0d0a5852f7ec158efdbace151cbb9e5e1c9c
|
data/alaska.js
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
var vm = require('vm');
|
2
|
+
var http = require("http");
|
3
|
+
var sandbox = vm.createContext({ console: {log: console.log}});
|
4
|
+
|
5
|
+
var contextOptions = {displayErrors: true};
|
6
|
+
var debugOpt = '--debug true';
|
7
|
+
var debug = false;
|
8
|
+
|
9
|
+
process.argv.forEach(function (val, index, array) {
|
10
|
+
if (debugOpt === val) {
|
11
|
+
debug = true;
|
12
|
+
}
|
13
|
+
});
|
14
|
+
|
15
|
+
var webPrint = function(res, respBody) {
|
16
|
+
res.writeHead(200, {'Connection': 'keep-alive'});
|
17
|
+
res.write(respBody);
|
18
|
+
res.end();
|
19
|
+
};
|
20
|
+
|
21
|
+
var server = http.createServer(function(req, res) {
|
22
|
+
var contents = '';
|
23
|
+
|
24
|
+
req.on('data', function (dataIn) {
|
25
|
+
contents += dataIn;
|
26
|
+
});
|
27
|
+
|
28
|
+
req.on('end', function () {
|
29
|
+
try {
|
30
|
+
var result = vm.runInContext(contents, sandbox, contextOptions);
|
31
|
+
if (typeof(result) == 'undefined' && result !== null) {
|
32
|
+
webPrint(res, '["ok"]');
|
33
|
+
} else {
|
34
|
+
try {
|
35
|
+
webPrint(res, JSON.stringify(['ok', result]));
|
36
|
+
} catch (err) {
|
37
|
+
webPrint(res, '["err"]');
|
38
|
+
}
|
39
|
+
}
|
40
|
+
} catch(err) {
|
41
|
+
webPrint(res, JSON.stringify(["err", err.toString()]));
|
42
|
+
}
|
43
|
+
});
|
44
|
+
});
|
45
|
+
|
46
|
+
var port = process.env.PORT || 3001;
|
47
|
+
server.listen(port);
|
48
|
+
|
49
|
+
if (debug) {
|
50
|
+
console.log('Listening on port:', port);
|
51
|
+
console.error('Alaska.js started. Piping coffee to warmer climates.');
|
52
|
+
}
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'socket'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
require 'execjs/runtime'
|
7
|
+
require 'execjs/module'
|
8
|
+
|
9
|
+
module Alaska
|
10
|
+
class Context < ExecJS::Runtime::Context
|
11
|
+
# runtime is an instance of Alaska
|
12
|
+
# src is the js code to be eval()'d in the nodejs context
|
13
|
+
def initialize(runtime, src = "") # third step, repeated .. yes, at least twice for common.css
|
14
|
+
@runtime = runtime
|
15
|
+
|
16
|
+
# compile context source, in most cases
|
17
|
+
# this is something like the CoffeeScript compiler
|
18
|
+
# or the SASS compiler
|
19
|
+
eval(src)
|
20
|
+
end
|
21
|
+
|
22
|
+
def eval(src)
|
23
|
+
if /\S/ =~ src #IMPORTANT! /\S/ =~ "()" => 0
|
24
|
+
exec(src)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def exec(src)
|
29
|
+
return "" unless src.length > 0
|
30
|
+
|
31
|
+
src = src.encode('UTF-8', :undef => :replace, :replace => '')
|
32
|
+
src = compile_source(src)
|
33
|
+
|
34
|
+
# src is either an empty object
|
35
|
+
# OR a valid JSON string in the form
|
36
|
+
# ['ok', 'result-of-coffeescript-or-sass-compiler']
|
37
|
+
# OR if an error occured
|
38
|
+
# ['err', 'some sort of error to be presented to the developer as a sprockets error']
|
39
|
+
#
|
40
|
+
status, value = src.empty? ? [] : ::JSON.parse(src, create_additions: false)
|
41
|
+
if status == "ok"
|
42
|
+
value
|
43
|
+
elsif value =~ /SyntaxError:/
|
44
|
+
raise ExecJS::RuntimeError, value
|
45
|
+
else
|
46
|
+
raise ExecJS::ProgramError, value
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def call(identifier, *args)
|
51
|
+
eval "#{identifier}.apply(this, #{::JSON.generate(args)})"
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def compile_source(contents)
|
57
|
+
sock = Net::BufferedIO.new(@runtime.provision_socket)
|
58
|
+
request = Net::HTTP::Post.new("/")
|
59
|
+
request['Connection'] = 'close'
|
60
|
+
request.body = contents
|
61
|
+
request.exec(sock, "1.1", "/")
|
62
|
+
|
63
|
+
begin
|
64
|
+
response = Net::HTTPResponse.read_new(sock)
|
65
|
+
end while response.kind_of?(Net::HTTPContinue)
|
66
|
+
|
67
|
+
response.reading_body(sock, request.response_body_permitted?) { }
|
68
|
+
sock.close
|
69
|
+
response.body
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
require 'execjs/runtime'
|
4
|
+
require 'execjs/module'
|
5
|
+
|
6
|
+
require 'alaska/context'
|
7
|
+
|
8
|
+
module Alaska
|
9
|
+
class Runtime < ExecJS::Runtime
|
10
|
+
attr_accessor :debug, :nodejs_cmd, :port, :pid, :semaphore
|
11
|
+
|
12
|
+
def initialize(opts = {})
|
13
|
+
srand
|
14
|
+
|
15
|
+
@debug = opts[:debug]
|
16
|
+
@nodejs_cmd = "node"
|
17
|
+
@pid = nil
|
18
|
+
@semaphore = Mutex.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def name
|
22
|
+
"Alaska"
|
23
|
+
end
|
24
|
+
|
25
|
+
def available?
|
26
|
+
#NOTE: this is brittle in terms of cross platform detection of node executable
|
27
|
+
`which #{@nodejs_cmd}`.strip.length > 0 # this must return true to be enabled
|
28
|
+
end
|
29
|
+
|
30
|
+
def deprecated?
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
def context_class
|
35
|
+
Alaska::Context
|
36
|
+
end
|
37
|
+
|
38
|
+
#NOTE: this should be thread-safe
|
39
|
+
def provision_socket
|
40
|
+
ensure_startup unless @pid
|
41
|
+
|
42
|
+
wait_socket = nil
|
43
|
+
checks = 0
|
44
|
+
max_retries = 12
|
45
|
+
|
46
|
+
while checks < max_retries
|
47
|
+
begin
|
48
|
+
checks += 1
|
49
|
+
wait_socket = UNIXSocket.new(@port)
|
50
|
+
break
|
51
|
+
rescue Errno::ENOENT, Errno::ECONNREFUSED, Errno::ENOTDIR
|
52
|
+
wait_socket = nil
|
53
|
+
sleep 0.5
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
if checks >= max_retries
|
58
|
+
ensure_shutdown
|
59
|
+
raise ExecJS::RuntimeError, "unable to connect to alaska.js server"
|
60
|
+
end
|
61
|
+
|
62
|
+
wait_socket
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def ensure_startup
|
68
|
+
@semaphore.synchronize {
|
69
|
+
return if @pid
|
70
|
+
|
71
|
+
@port = begin
|
72
|
+
tmpfile = Tempfile.new("alaska")
|
73
|
+
path = tmpfile.path
|
74
|
+
tmpfile.close
|
75
|
+
tmpfile.unlink
|
76
|
+
path
|
77
|
+
end
|
78
|
+
|
79
|
+
alaska_js_path = File.join(File.dirname(File.expand_path(__FILE__)), '../../alaska.js')
|
80
|
+
command_options = [alaska_js_path, "--debug #{!!@debug}"] # --other --command-line --options --go --here
|
81
|
+
|
82
|
+
@pid = Process.spawn({"PORT" => @port.to_s}, @nodejs_cmd, *command_options, {:err => :out})
|
83
|
+
|
84
|
+
at_exit do
|
85
|
+
ensure_shutdown
|
86
|
+
end
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
def ensure_shutdown
|
91
|
+
return unless @pid
|
92
|
+
|
93
|
+
Process.kill("TERM", @pid) rescue Errno::ECHILD
|
94
|
+
Process.wait(@pid) rescue Errno::ECHILD
|
95
|
+
|
96
|
+
@port = nil
|
97
|
+
@pid = nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: alaska
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jon Bardin
|
8
|
+
- Stephen Grider
|
9
|
+
- Ville Lautanala
|
10
|
+
- Giovanni Bonetti
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
date: 2015-02-10 00:00:00.000000000 Z
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: execjs
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - "~>"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2.6'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.6'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - "~>"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '10.4'
|
37
|
+
type: :development
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '10.4'
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: minitest
|
46
|
+
requirement: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - "~>"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '5.5'
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - "~>"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '5.5'
|
58
|
+
description: uses a single shared nodejs process to handle ExecJS::Runtime evaluation
|
59
|
+
email: diclophis@gmail.com
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- alaska.js
|
65
|
+
- lib/alaska/context.rb
|
66
|
+
- lib/alaska/runtime.rb
|
67
|
+
homepage: https://github.com/mavenlink/alaska
|
68
|
+
licenses:
|
69
|
+
- MIT
|
70
|
+
metadata: {}
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
requirements: []
|
86
|
+
rubyforge_project:
|
87
|
+
rubygems_version: 2.4.8
|
88
|
+
signing_key:
|
89
|
+
specification_version: 4
|
90
|
+
summary: persistent ExecJS runtime
|
91
|
+
test_files: []
|