h8 0.4.11 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -0
- data/bin/h8 +4 -1
- data/ext/h8/h8.cpp +13 -7
- data/ext/h8/h8.h +1 -1
- data/ext/h8/main.cpp +2 -1
- data/ext/h8/ruby_gate.h +9 -4
- data/lib/h8.rb +1 -1
- data/lib/h8/command.rb +20 -11
- data/lib/h8/context.rb +22 -1
- data/lib/h8/errors.rb +7 -0
- data/lib/h8/tools.rb +3 -2
- data/lib/h8/version.rb +1 -1
- data/spec/command_spec.rb +1 -7
- data/spec/heavy_load_spec.rb +96 -0
- data/spec/js_gate_spec.rb +4 -2
- data/spec/ruby_gate_spec.rb +15 -4
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3c42fdc46126f4cd9b55893dcf773b531f27dfb
|
4
|
+
data.tar.gz: 2b6b7b9157cd99488987657a34cbbf3449b504a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e4443044d235df479575c0db14d79060c3318364c8c535920d3ca4f2b074a1100813c56e8121cbf2946d9db293c82bfd0a81d252b28eda823b6563f0eac48a0
|
7
|
+
data.tar.gz: 5d5fa89d8992e39fd03264b2323f78965c55cfc4dada8d2aa9bb57b3e139807a0077e81af3143c5aec9bc0218617b369d7679bfe5bb087a816c681b95e75fa88
|
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Hybrid8, aka H8
|
2
2
|
|
3
|
+
*version 0.5* breaks the way nested exceptions are passed. Now riby -> js -> ruby uncaught
|
4
|
+
exception is wrapped into H8::NestedError so one can get both ruby and javascript trace.
|
5
|
+
|
3
6
|
_Warning_ this gem is in public beta at the moment - beta testers are welcome! It means it's not
|
4
7
|
yet stable enough for running in production - we haven't tried it yet ourselves.
|
5
8
|
|
data/bin/h8
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
#!/bin/env ruby
|
2
|
-
|
2
|
+
#
|
3
|
+
#
|
4
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../lib/h8")
|
3
5
|
require 'h8/command'
|
4
6
|
|
5
7
|
cmd = nil
|
6
8
|
begin
|
7
9
|
cmd = H8::Command.new(*ARGV)
|
10
|
+
rescue SystemExit
|
8
11
|
rescue Exception => e
|
9
12
|
STDERR.puts "Error: #{e}\n\n#{e.backtrace.join("\n")}"
|
10
13
|
STDERR.puts cmd.usage
|
data/ext/h8/h8.cpp
CHANGED
@@ -18,22 +18,28 @@ void h8::JsError::raise() const {
|
|
18
18
|
Local<Object> jsx = exception().As<Object>();
|
19
19
|
Local<Value> source = jsx->Get(h8->js("source"));
|
20
20
|
RubyGate *rg = RubyGate::unwrap(source.As<Object>());
|
21
|
-
if (rg) {
|
22
|
-
// Passing thru the Ruby exception
|
23
|
-
ruby_exception = rg->rubyObject();
|
24
|
-
} else {
|
21
|
+
// if (rg) {
|
22
|
+
// // Passing thru the Ruby exception
|
23
|
+
// ruby_exception = rg->rubyObject();
|
24
|
+
// } else {
|
25
25
|
Local<Message> m = message();
|
26
26
|
Local<String> s = m->Get();
|
27
27
|
String::Utf8Value res(s->ToString());
|
28
|
-
|
28
|
+
|
29
|
+
VALUE ex_class = rg ? js_nested_exception : js_exception;
|
30
|
+
ruby_exception = rb_exc_new2(ex_class,
|
29
31
|
*res ? *res : "unknown javascript exception");
|
32
|
+
|
30
33
|
rb_iv_set(ruby_exception, "@message", h8->to_ruby(s));
|
31
34
|
rb_iv_set(ruby_exception, "@javascript_error",
|
32
35
|
h8->to_ruby(jsx));
|
33
36
|
rb_iv_set(ruby_exception, "@origin_name", h8->to_ruby(m->GetScriptResourceName()));
|
34
37
|
rb_iv_set(ruby_exception, "@origin_line", INT2FIX(m->GetLineNumber()));
|
35
38
|
rb_iv_set(ruby_exception, "@origin_column", INT2FIX(m->GetEndColumn()));
|
36
|
-
|
39
|
+
if( rg ) {
|
40
|
+
rb_iv_set(ruby_exception, "@ruby_error", rg->rubyObject());
|
41
|
+
}
|
42
|
+
// }
|
37
43
|
}
|
38
44
|
rb_exc_raise(ruby_exception);
|
39
45
|
// }
|
@@ -180,7 +186,7 @@ void h8::H8::register_ruby_gate(RubyGate* gate) {
|
|
180
186
|
}
|
181
187
|
|
182
188
|
void h8::H8::unregister_ruby_gate(RubyGate* gate) {
|
183
|
-
|
189
|
+
gate->unlink();
|
184
190
|
id_map.erase(gate->ruby_object);
|
185
191
|
}
|
186
192
|
|
data/ext/h8/h8.h
CHANGED
@@ -13,7 +13,7 @@
|
|
13
13
|
using namespace v8;
|
14
14
|
using namespace std;
|
15
15
|
|
16
|
-
extern VALUE h8_exception, js_exception, js_timeout_exception;
|
16
|
+
extern VALUE h8_exception, js_exception, js_timeout_exception, js_nested_exception;
|
17
17
|
extern VALUE context_class;
|
18
18
|
extern VALUE value_class;
|
19
19
|
extern VALUE ruby_gate_class;
|
data/ext/h8/main.cpp
CHANGED
@@ -8,7 +8,7 @@ extern "C" {
|
|
8
8
|
void Init_h8(void);
|
9
9
|
}
|
10
10
|
|
11
|
-
VALUE h8_exception, js_exception, js_timeout_exception;
|
11
|
+
VALUE h8_exception, js_exception, js_timeout_exception, js_nested_exception;
|
12
12
|
VALUE context_class;
|
13
13
|
VALUE ruby_gate_class;
|
14
14
|
VALUE value_class;
|
@@ -231,6 +231,7 @@ void Init_h8(void) {
|
|
231
231
|
|
232
232
|
h8_exception = rb_define_class_under(h8, "Error", rb_eStandardError);
|
233
233
|
js_exception = rb_define_class_under(h8, "JsError", h8_exception);
|
234
|
+
js_nested_exception = rb_define_class_under(h8, "NestedError", js_exception);
|
234
235
|
js_timeout_exception = rb_define_class_under(h8, "TimeoutError",
|
235
236
|
js_exception);
|
236
237
|
|
data/ext/h8/ruby_gate.h
CHANGED
@@ -42,7 +42,9 @@ public:
|
|
42
42
|
|
43
43
|
virtual void free() {
|
44
44
|
// printf("RG::FREE(%p)\n", this);
|
45
|
-
|
45
|
+
context->unregister_ruby_gate(this);
|
46
|
+
context = 0;
|
47
|
+
// delete this;
|
46
48
|
}
|
47
49
|
|
48
50
|
VALUE rubyObject() const {
|
@@ -51,9 +53,12 @@ public:
|
|
51
53
|
|
52
54
|
virtual ~RubyGate() {
|
53
55
|
// puts("~RG()");
|
54
|
-
|
55
|
-
|
56
|
-
|
56
|
+
if( context ) {
|
57
|
+
// puts("rg2");
|
58
|
+
context->unregister_ruby_gate(this);
|
59
|
+
}
|
60
|
+
// persistent().ClearWeak();
|
61
|
+
// persistent().Reset();
|
57
62
|
// The rest is done by the base classes
|
58
63
|
}
|
59
64
|
|
data/lib/h8.rb
CHANGED
data/lib/h8/command.rb
CHANGED
@@ -7,11 +7,19 @@ module H8
|
|
7
7
|
|
8
8
|
class Command
|
9
9
|
|
10
|
-
def initialize *args, out: STDOUT, err: STDERR
|
10
|
+
def initialize *args, out: STDOUT, err: STDERR, dont_run: false
|
11
11
|
@out = out
|
12
12
|
@err = err
|
13
13
|
|
14
|
-
run *args
|
14
|
+
run *args unless dont_run
|
15
|
+
end
|
16
|
+
|
17
|
+
def usage
|
18
|
+
puts "h8 #{H8::VERSION} CLI runner\n"
|
19
|
+
puts "Usage:\n h8 [keys] file1..."
|
20
|
+
puts
|
21
|
+
puts "executes 1 or more javascript/coffeescript files connected with Ruby environment"
|
22
|
+
puts @parser.keys_doc
|
15
23
|
end
|
16
24
|
|
17
25
|
def run *args
|
@@ -33,8 +41,12 @@ module H8
|
|
33
41
|
count += 1
|
34
42
|
end
|
35
43
|
}
|
44
|
+
.key('-h', '--h') {
|
45
|
+
usage
|
46
|
+
count = -100000000
|
47
|
+
}
|
36
48
|
|
37
|
-
@parser.parse { |file|
|
49
|
+
rest = @parser.parse { |file|
|
38
50
|
count += 1
|
39
51
|
@script = open(file, 'r').read
|
40
52
|
file.downcase.end_with?('.coffee') and @script = H8::Coffee.compile(@script)
|
@@ -42,7 +54,10 @@ module H8
|
|
42
54
|
context.eval @script
|
43
55
|
}
|
44
56
|
|
45
|
-
count
|
57
|
+
unless count != 0
|
58
|
+
STDERR.puts 'H8: error: provide at least one file (use -h for help)'
|
59
|
+
exit 300
|
60
|
+
end
|
46
61
|
end
|
47
62
|
|
48
63
|
def context
|
@@ -55,17 +70,11 @@ module H8
|
|
55
70
|
cxt[:puts] = print
|
56
71
|
cxt[:open] = -> (name, mode='r', block=nil) { Stream.new(name, mode, block) }
|
57
72
|
cxt['__FILE__'] = @file ? @file.to_s : '<inline>'
|
58
|
-
cxt[:File]
|
73
|
+
cxt[:File] = FileProxy.new
|
59
74
|
cxt
|
60
75
|
end
|
61
76
|
end
|
62
77
|
|
63
|
-
def usage
|
64
|
-
"\nh8 #{H8::VERSION} CLI inteface\n\n" +
|
65
|
-
"Usage: h8 <file.js/file.coffe>\n\n" +
|
66
|
-
@parser.keys_doc
|
67
|
-
end
|
68
|
-
|
69
78
|
class FileProxy
|
70
79
|
def dirname str
|
71
80
|
File.dirname str
|
data/lib/h8/context.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'h8'
|
3
3
|
|
4
|
+
class Array
|
5
|
+
def _select_js callable
|
6
|
+
select { |item|
|
7
|
+
callable.call item
|
8
|
+
}
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
4
12
|
module H8
|
5
13
|
|
6
14
|
class Context
|
@@ -68,6 +76,9 @@ module H8
|
|
68
76
|
# It has very complex logic so the security model update should be done somehow
|
69
77
|
# else.
|
70
78
|
def self.secure_call instance, method, args=nil
|
79
|
+
if instance.is_a?(Array)
|
80
|
+
method == 'select' and method = '_select_js'
|
81
|
+
end
|
71
82
|
method = method.to_sym
|
72
83
|
begin
|
73
84
|
m = instance.public_method(method)
|
@@ -110,7 +121,16 @@ module H8
|
|
110
121
|
# This is workaround for buggy rb_proc_call which produces segfaults
|
111
122
|
# if proc is not exactly a proc, so we call it like this:
|
112
123
|
def safe_proc_call proc, args
|
113
|
-
proc.call
|
124
|
+
if proc.respond_to?(:call)
|
125
|
+
proc.call(*args)
|
126
|
+
else
|
127
|
+
if args.length == 0
|
128
|
+
proc # Popular bug: call no-arg method not like a property
|
129
|
+
else
|
130
|
+
raise NoMethodError, "Invalid callable"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
# proc.is_a?(Array) ? proc : proc.call(*args)
|
114
134
|
end
|
115
135
|
|
116
136
|
# :nodoc:
|
@@ -127,6 +147,7 @@ module H8
|
|
127
147
|
end
|
128
148
|
|
129
149
|
def self.can_access?(owner)
|
150
|
+
return true if owner.is_a?(Array.class)
|
130
151
|
owner != Object.class && owner != Kernel && owner != BasicObject.class
|
131
152
|
end
|
132
153
|
|
data/lib/h8/errors.rb
CHANGED
@@ -39,6 +39,13 @@ module H8
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
# The exception that carries out uncaught ruby exception #ruby_error
|
43
|
+
# therefore it is possible to get javascript backtrace too
|
44
|
+
class NestedError < JsError
|
45
|
+
# The uncaught ruby exception
|
46
|
+
attr :ruby_error
|
47
|
+
end
|
48
|
+
|
42
49
|
# Script execution is timed out (see H8::Context#eval timeout parameter)
|
43
50
|
class TimeoutError < JsError
|
44
51
|
def initialize message
|
data/lib/h8/tools.rb
CHANGED
@@ -2,7 +2,7 @@ require 'singleton'
|
|
2
2
|
|
3
3
|
module H8
|
4
4
|
# The class representing undefined in javascript. Singleton
|
5
|
-
#
|
5
|
+
# Note that H8::Undefined == false but is not FalseClass
|
6
6
|
class UndefinedClass
|
7
7
|
include Singleton
|
8
8
|
|
@@ -29,13 +29,13 @@ module H8
|
|
29
29
|
def == x
|
30
30
|
x.is_a?(H8::UndefinedClass) || x == false
|
31
31
|
end
|
32
|
-
|
33
32
|
end
|
34
33
|
|
35
34
|
# The constant representing 'undefined' value in Javascript
|
36
35
|
# The proper use is to compare returned value res == H8::Undefined
|
37
36
|
Undefined = UndefinedClass.instance
|
38
37
|
|
38
|
+
|
39
39
|
# Convert javascript 'arguments' object to ruby array
|
40
40
|
def arguments_to_a args
|
41
41
|
res = Array.new(l=args.length)
|
@@ -45,3 +45,4 @@ module H8
|
|
45
45
|
|
46
46
|
module_function :arguments_to_a
|
47
47
|
end
|
48
|
+
|
data/lib/h8/version.rb
CHANGED
data/spec/command_spec.rb
CHANGED
@@ -7,7 +7,7 @@ describe 'cli' do
|
|
7
7
|
before :each do
|
8
8
|
@out = StringIO.new '', 'w'
|
9
9
|
@err = StringIO.new '', 'w'
|
10
|
-
@command = H8::Command.new out: @out, err: @err
|
10
|
+
@command = H8::Command.new out: @out, err: @err, dont_run: true
|
11
11
|
end
|
12
12
|
|
13
13
|
def output
|
@@ -29,12 +29,6 @@ describe 'cli' do
|
|
29
29
|
File.expand_path(File.join(File.dirname(__FILE__), *path_components))
|
30
30
|
end
|
31
31
|
|
32
|
-
it 'should print usage' do
|
33
|
-
expect(-> { @command.run }).to raise_error(RuntimeError, "Must provide at least one file")
|
34
|
-
expect(@command.usage =~ /Usage:/).to be_truthy
|
35
|
-
# puts @command.usage
|
36
|
-
end
|
37
|
-
|
38
32
|
it 'should print' do
|
39
33
|
run 'print "hello"; console.log "world"; console.error "life sucks!"'
|
40
34
|
output.should == "hello\nworld\n"
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'h8'
|
3
|
+
require 'ostruct'
|
4
|
+
require 'hashie'
|
5
|
+
|
6
|
+
desk_gen = <<END
|
7
|
+
console.log 'started'
|
8
|
+
|
9
|
+
offsets = [[-1, 0], [0, 1], [1, 0], [0, -1]]
|
10
|
+
|
11
|
+
class DeskGenerator
|
12
|
+
|
13
|
+
constructor: (@n, r0=0, c0=0) ->
|
14
|
+
@desk = []
|
15
|
+
for r in [0...@n]
|
16
|
+
@desk.push (null for col in [0...@n])
|
17
|
+
@retries = 0
|
18
|
+
@step(r0, c0, @n * @n) or throw new Error("Failed to generate desk")
|
19
|
+
|
20
|
+
step: (r, c, depth) ->
|
21
|
+
@desk[r][c] = depth--
|
22
|
+
console.log r, c, depth
|
23
|
+
return true if depth == 0
|
24
|
+
|
25
|
+
for [r1, c1] in @moves(r, c)
|
26
|
+
return true if @step(r1, c1, depth)
|
27
|
+
|
28
|
+
@retries++
|
29
|
+
depth++
|
30
|
+
@desk[r][c] = null
|
31
|
+
false
|
32
|
+
|
33
|
+
moves: (r, c) ->
|
34
|
+
moves = []
|
35
|
+
for [sr, sc] in offsets
|
36
|
+
[r1, c1] = [r + sr, c + sc]
|
37
|
+
if 0 <= r1 < @n && 0 <= c1 < @n && !@desk[r1][c1]
|
38
|
+
moves.push [r1, c1]
|
39
|
+
moves
|
40
|
+
|
41
|
+
toString: ->
|
42
|
+
res = []
|
43
|
+
for r in [0...@n]
|
44
|
+
res.push ( (if x == 0 then ' .' else pad(x, 3)) for x in @desk[r]).join('')
|
45
|
+
res.join "\n"
|
46
|
+
|
47
|
+
pad = (n, len) ->
|
48
|
+
len ?= 3
|
49
|
+
res = n?.toString() || '.'
|
50
|
+
res = ' ' + res while res.length < len
|
51
|
+
res
|
52
|
+
|
53
|
+
timing = (name, cb) ->
|
54
|
+
start = new Date().getTime()
|
55
|
+
res = cb()
|
56
|
+
console.log("\#{name}: \#{(new Date().getTime() - start) / 1000}")
|
57
|
+
res
|
58
|
+
|
59
|
+
result = timing 'default', ->
|
60
|
+
new DeskGenerator(6, 5, 1)
|
61
|
+
|
62
|
+
console.log result.toString()
|
63
|
+
console.log 'retries',result.retries
|
64
|
+
END
|
65
|
+
|
66
|
+
class Console
|
67
|
+
def debug *args
|
68
|
+
log *args
|
69
|
+
end
|
70
|
+
|
71
|
+
def log *args
|
72
|
+
# puts *args.join(' ')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'heavy scripts' do
|
77
|
+
it 'should pass desk gen test' do
|
78
|
+
c = H8::Context.new
|
79
|
+
c[:console] = Console.new
|
80
|
+
# c.eval "console.log('fine');"
|
81
|
+
# pending
|
82
|
+
js = H8::Coffee.compile desk_gen
|
83
|
+
begin
|
84
|
+
c.eval js
|
85
|
+
rescue
|
86
|
+
n = 1
|
87
|
+
js.each_line { |l|
|
88
|
+
puts "%3d %s" % [n, l]
|
89
|
+
n += 1
|
90
|
+
}
|
91
|
+
raise
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
|
data/spec/js_gate_spec.rb
CHANGED
@@ -274,7 +274,7 @@ describe 'js_gate' do
|
|
274
274
|
}).to raise_error(H8::JsError)
|
275
275
|
end
|
276
276
|
|
277
|
-
it 'should
|
277
|
+
it 'should report thru uncaught ruby exceptions from js->ruby callbacks' do
|
278
278
|
class MyException < StandardError;
|
279
279
|
end;
|
280
280
|
cxt = H8::Context.new
|
@@ -287,7 +287,9 @@ describe 'js_gate' do
|
|
287
287
|
End
|
288
288
|
expect(-> {
|
289
289
|
res.call('foo', 'bar').should == 'foo:bar'
|
290
|
-
}).to raise_error(
|
290
|
+
}).to raise_error(H8::NestedError) { |e|
|
291
|
+
e.ruby_error.should be_instance_of(MyException)
|
292
|
+
}
|
291
293
|
end
|
292
294
|
|
293
295
|
it 'should dynamically add and remove properties to js objects' do
|
data/spec/ruby_gate_spec.rb
CHANGED
@@ -135,8 +135,9 @@ describe 'ruby gate' do
|
|
135
135
|
result = fn(11, 22);
|
136
136
|
throw Error("It should not happen");
|
137
137
|
End
|
138
|
-
}).to raise_error(
|
139
|
-
e.
|
138
|
+
}).to raise_error(H8::NestedError) { |e|
|
139
|
+
e.ruby_error.should be_instance_of(MyException)
|
140
|
+
e.ruby_error.message.should == 'Shit happens'
|
140
141
|
}
|
141
142
|
end
|
142
143
|
|
@@ -295,7 +296,7 @@ describe 'ruby gate' do
|
|
295
296
|
# see Test class implementation: this is a valid test
|
296
297
|
cxt.eval("t['foo'];").should == 'init[]'
|
297
298
|
cxt.eval("t.foo").should == 'init[]'
|
298
|
-
expect(-> { cxt.eval("t['foo1'];") }).to raise_error(
|
299
|
+
expect(-> { cxt.eval("t['foo1'];") }).to raise_error(H8::NestedError)
|
299
300
|
cxt.eval("t.foo='bar'");
|
300
301
|
cxt.eval("t.foo;").should == 'bar'
|
301
302
|
t.val.should == 'bar'
|
@@ -366,6 +367,14 @@ describe 'ruby gate' do
|
|
366
367
|
h['one'].should == 1
|
367
368
|
end
|
368
369
|
|
370
|
+
it 'should access ruby and java array functions' do
|
371
|
+
cxt = H8::Context.new
|
372
|
+
src = cxt[:h] = [1,20,3,4,5]
|
373
|
+
cxt.eval("h.reverse()").should == [5, 4, 3, 20, 1]
|
374
|
+
cxt.eval("h.sort()").should == [1,3,4,5,20]
|
375
|
+
cxt.eval("h.select(function(x){return x >=4;}).sort()").should == [4, 5, 20]
|
376
|
+
end
|
377
|
+
|
369
378
|
it 'should pass varargs' do
|
370
379
|
cxt = H8::Context.new
|
371
380
|
cxt[:test] = -> (args) {
|
@@ -448,7 +457,9 @@ describe 'ruby gate' do
|
|
448
457
|
|
449
458
|
# We call gated ruby object with wrong number of args
|
450
459
|
# which in turn causes attempt to call not callable result:
|
451
|
-
expect(-> { cxt.eval('g1.checkself(12)') }).to raise_error(
|
460
|
+
expect(-> { cxt.eval('g1.checkself(12)') }).to raise_error(H8::NestedError) { |e|
|
461
|
+
e.ruby_error.should be_instance_of(NoMethodError)
|
462
|
+
}
|
452
463
|
end
|
453
464
|
|
454
465
|
it 'should return self from gated class' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: h8
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- sergeych
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -153,6 +153,7 @@ files:
|
|
153
153
|
- spec/coffee_spec.rb
|
154
154
|
- spec/command_spec.rb
|
155
155
|
- spec/context_spec.rb
|
156
|
+
- spec/heavy_load_spec.rb
|
156
157
|
- spec/js_gate_spec.rb
|
157
158
|
- spec/ruby_gate_spec.rb
|
158
159
|
- spec/spec_helper.rb
|
@@ -178,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
178
179
|
version: '0'
|
179
180
|
requirements: []
|
180
181
|
rubyforge_project:
|
181
|
-
rubygems_version: 2.
|
182
|
+
rubygems_version: 2.4.5
|
182
183
|
signing_key:
|
183
184
|
specification_version: 4
|
184
185
|
summary: Minimalistic and fast Ruby <--> V8 integration
|
@@ -187,6 +188,7 @@ test_files:
|
|
187
188
|
- spec/coffee_spec.rb
|
188
189
|
- spec/command_spec.rb
|
189
190
|
- spec/context_spec.rb
|
191
|
+
- spec/heavy_load_spec.rb
|
190
192
|
- spec/js_gate_spec.rb
|
191
193
|
- spec/ruby_gate_spec.rb
|
192
194
|
- spec/spec_helper.rb
|