node_module 0.1.4 → 0.2.1
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/.ruby-version +1 -1
- data/README.md +50 -17
- data/lib/node_module.rb +19 -17
- data/lib/node_module/compiled.rb +37 -0
- data/lib/node_module/opal_js_context.rb +1 -1
- data/lib/node_module/version.rb +1 -1
- data/node_module.gemspec +2 -2
- data/spec/lib/node_module/compiled_spec.rb +35 -0
- data/spec/lib/node_module/opal_js_context_spec.rb +0 -7
- metadata +28 -45
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3733f5f0dd05b4473cb33699578a943e1c69079b
|
4
|
+
data.tar.gz: 398599f46b2ca163d65dc4d82c56cb37e9b12530
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6fafb546557516ff3419fb84d2aa81de3f3d5e673ac1196e9e9cc313904f57497b242ceba9cd536eff90023f3f8bd034eeba0925b9f13e68b89463db6e4b9bac
|
7
|
+
data.tar.gz: adf184d471553503ff448413479119783108277f09060adb13d48e6ea32398c55cd8ada72abc61f838e2d58414a4fb94c1fed5fdc6a7cf00ebe1fd85805afbe3
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
2.1.0
|
data/README.md
CHANGED
@@ -15,12 +15,10 @@ On the other hand, it has a couple of major advantages over every other language
|
|
15
15
|
1. It's web-scale
|
16
16
|
2. It's *web-scale*!
|
17
17
|
|
18
|
-
Wouldn't it be nice if you could drop down to Node... *implicitly*?
|
19
|
-
You wouldn't need to significantly change anything to fine-tune
|
20
|
-
portions of your app, right down to the individual method level.
|
18
|
+
Wouldn't it be nice if you could drop down to Node... *implicitly*? You wouldn't need to significantly change anything to fine-tune portions of your app, right down to the individual method level.
|
21
19
|
|
22
20
|
Enter `node_module`, which does just that. All you need to do is add the gem, and
|
23
|
-
tell it which methods you want to run as
|
21
|
+
tell it which methods or classes you want to run as JavaScript instead of Ruby.
|
24
22
|
|
25
23
|
## How to install
|
26
24
|
|
@@ -38,6 +36,7 @@ gem install node_module
|
|
38
36
|
|
39
37
|
## How to use
|
40
38
|
|
39
|
+
### Turn certain methods into JavaScript
|
41
40
|
```ruby
|
42
41
|
require 'node_module'
|
43
42
|
|
@@ -57,10 +56,10 @@ class AbstractConcepts
|
|
57
56
|
42
|
58
57
|
end
|
59
58
|
|
60
|
-
# run a specific method as
|
59
|
+
# run a specific method as JavaScript
|
61
60
|
node_module :meaning_of_life
|
62
61
|
|
63
|
-
# run everything after this point as
|
62
|
+
# run everything after this point as JavaScript
|
64
63
|
node_module
|
65
64
|
|
66
65
|
def pythagorean_triplet?(a, b, c)
|
@@ -69,23 +68,57 @@ class AbstractConcepts
|
|
69
68
|
end
|
70
69
|
```
|
71
70
|
|
72
|
-
`node_module` behaves like the `public`, `private`, and `protected`
|
73
|
-
|
74
|
-
|
75
|
-
|
71
|
+
`node_module` behaves like the `public`, `private`, and `protected` methods Ruby gives you. You can pass in specific methods as symbols, or call it without any arguments to change every subsequently defined method.
|
72
|
+
|
73
|
+
If you're using Ruby 2.1 you can also turn a single method into JS like this:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
node_module def method
|
77
|
+
# stuff
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
### Turn an *entire class* into JavaScript
|
82
|
+
|
83
|
+
Your mileage may vary with this one. Use it at your own risk.
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
require 'node_module'
|
87
|
+
|
88
|
+
class MentalState < NodeModule::Compiled
|
89
|
+
|
90
|
+
def initialize(mental_state)
|
91
|
+
@mental_state = mental_state
|
92
|
+
end
|
93
|
+
|
94
|
+
def happy?
|
95
|
+
@mental_state == "happy"
|
96
|
+
end
|
97
|
+
|
98
|
+
def sad?
|
99
|
+
@mental_state == "sad"
|
100
|
+
end
|
101
|
+
|
102
|
+
def utterly_fucking_bonkers?
|
103
|
+
true
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
```
|
108
|
+
|
109
|
+
Note that you might have a lot of difficulty getting classes to talk to each
|
110
|
+
other, because of the way objects are scoped when executing methods.
|
76
111
|
|
77
|
-
This is a ridiculous proof of concept, so there are a few issues...
|
78
112
|
|
79
113
|
## Current limitations
|
80
114
|
|
81
|
-
|
82
|
-
|
115
|
+
This is a ridiculous proof of concept, so there are a few issues...
|
116
|
+
|
117
|
+
- Calling one compiled method/class in the context of another will blow up, so no dependency injection or any of that.
|
83
118
|
|
84
|
-
- It's destructive, so you'll lose the body of the original
|
85
|
-
method. This means you can't yet switch a method between its Ruby
|
86
|
-
and Javascript versions.
|
119
|
+
- It's destructive, so you'll lose the body of the original method.
|
87
120
|
|
88
|
-
- It doesn't actually use Node yet
|
121
|
+
- It doesn't actually use Node yet, just V8.
|
89
122
|
|
90
123
|
- It probably can't handle anything too clever.
|
91
124
|
|
data/lib/node_module.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
-
require 'node_module/version'
|
2
1
|
require 'live_ast/to_ruby'
|
3
2
|
require 'live_ast/irb_spy' if defined?(IRB)
|
4
3
|
|
4
|
+
require 'node_module/version'
|
5
|
+
|
5
6
|
module NodeModule
|
6
7
|
|
7
8
|
autoload :OpalJsContext, 'node_module/opal_js_context'
|
9
|
+
autoload :Compiled, 'node_module/compiled'
|
8
10
|
|
9
|
-
def self.included(
|
10
|
-
|
11
|
+
def self.included(receiver)
|
12
|
+
receiver.extend ClassMethods
|
11
13
|
end
|
12
14
|
|
13
15
|
def self.opal_js_context
|
@@ -17,35 +19,35 @@ module NodeModule
|
|
17
19
|
module ClassMethods
|
18
20
|
def node_module(*methods)
|
19
21
|
if methods.empty?
|
20
|
-
NodeModule.
|
22
|
+
NodeModule.compile_on_callback(self)
|
21
23
|
else
|
22
|
-
NodeModule.
|
24
|
+
NodeModule.compile_and_replace!(self, methods)
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
def self.execute_methods_as_javascript!(methods, receiver)
|
29
|
+
def self.compile_and_replace!(receiver, methods)
|
30
30
|
methods.each do |name|
|
31
31
|
meth = receiver.instance_method(name).to_ruby
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
receiver.send :define_method, name do |*args|
|
36
|
-
NodeModule.opal_js_context.run(__method__, args)
|
37
|
-
end
|
32
|
+
self.opal_js_context.compile(meth)
|
33
|
+
self.replace_method!(receiver, name)
|
38
34
|
end
|
39
35
|
end
|
40
36
|
|
41
|
-
def self.
|
37
|
+
def self.compile_on_callback(receiver)
|
42
38
|
active = nil
|
43
|
-
receiver.define_singleton_method(:method_added) do |
|
39
|
+
receiver.define_singleton_method(:method_added) do |name|
|
44
40
|
return if active
|
45
41
|
active = true
|
46
|
-
receiver.node_module(
|
42
|
+
receiver.node_module(name)
|
47
43
|
active = false
|
48
44
|
end
|
49
45
|
end
|
50
46
|
|
47
|
+
def self.replace_method!(receiver, name)
|
48
|
+
receiver.send :define_method, name do |*args|
|
49
|
+
NodeModule.opal_js_context.run(__method__, args)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
51
53
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
|
3
|
+
module NodeModule
|
4
|
+
class Compiled
|
5
|
+
|
6
|
+
def self.inherited(receiver)
|
7
|
+
source = File.read(caller.first[/^[^:]+/])
|
8
|
+
|
9
|
+
extract_class_definition(source) do |class_def|
|
10
|
+
NodeModule.opal_js_context.compile(class_def)
|
11
|
+
end
|
12
|
+
|
13
|
+
receiver.extend NodeModule::ClassMethods
|
14
|
+
|
15
|
+
NodeModule.compile_on_callback(receiver)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.extract_class_definition(source)
|
21
|
+
scanner = StringScanner.new(source)
|
22
|
+
scanner.scan_until(/^\s+class/)
|
23
|
+
|
24
|
+
indent = scanner.matched[/[^\n]\s+/].length
|
25
|
+
scanner.pos = scanner.pos - scanner.matched_size
|
26
|
+
|
27
|
+
definition = scanner.scan_until(/^\s{#{indent}}end/)
|
28
|
+
.sub('< NodeModule::Compiled', '')
|
29
|
+
|
30
|
+
yield definition
|
31
|
+
|
32
|
+
ensure
|
33
|
+
scanner.terminate
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
data/lib/node_module/version.rb
CHANGED
data/node_module.gemspec
CHANGED
@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_dependency "live_ast"
|
22
22
|
spec.add_dependency "therubyracer"
|
23
|
-
spec.add_dependency "opal"
|
23
|
+
spec.add_dependency "opal", "~> 0.5"
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
25
25
|
spec.add_development_dependency "rake"
|
26
|
-
spec.add_development_dependency "minitest"
|
26
|
+
spec.add_development_dependency "minitest", "~> 5.2.3"
|
27
27
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe NodeModule::Compiled, "run entire class against V8" do
|
4
|
+
|
5
|
+
class Greeter < NodeModule::Compiled
|
6
|
+
|
7
|
+
def initialize(*names)
|
8
|
+
@names = names
|
9
|
+
end
|
10
|
+
|
11
|
+
def hello!
|
12
|
+
@names.map {|name| "hello #{name}!" }.join(" ")
|
13
|
+
end
|
14
|
+
|
15
|
+
def goodbye!
|
16
|
+
hello!.gsub('hello', 'goodbye')
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "integration with the subclass" do
|
22
|
+
|
23
|
+
let(:greeter) { Greeter.new("Sarah", "Jess") }
|
24
|
+
|
25
|
+
it "says 'hello' to all the people" do
|
26
|
+
greeter.hello!.must_equal "hello Sarah! hello Jess!"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "says 'goodbye' to all the people" do
|
30
|
+
greeter.goodbye!.must_equal "goodbye Sarah! goodbye Jess!"
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -8,13 +8,6 @@ describe NodeModule::OpalJsContext do
|
|
8
8
|
let(:bang_method) { "def boom!; 'BOOM!'; end;" }
|
9
9
|
let(:mixed_method) { "def boom?(a, b); boom! if a == b; end;" }
|
10
10
|
|
11
|
-
describe "#load" do
|
12
|
-
it "successfully turns Ruby into Opal-style Javascript" do
|
13
|
-
js = subject.compile(predicate_method)
|
14
|
-
js.to_s.must_match /function \(a, b\) \{\s+ return a\['\$=='\]\(b\);\s+\}/
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
11
|
describe "#run" do
|
19
12
|
before do
|
20
13
|
subject.compile(predicate_method)
|
metadata
CHANGED
@@ -1,112 +1,99 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: node_module
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Lee Machin
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-02-16 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: live_ast
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: therubyracer
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: opal
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - "~>"
|
52
46
|
- !ruby/object:Gem::Version
|
53
|
-
version: '0'
|
47
|
+
version: '0.5'
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - "~>"
|
60
53
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
54
|
+
version: '0.5'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: bundler
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- - ~>
|
59
|
+
- - "~>"
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '1.3'
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- - ~>
|
66
|
+
- - "~>"
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: '1.3'
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: rake
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - ">="
|
84
74
|
- !ruby/object:Gem::Version
|
85
75
|
version: '0'
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - ">="
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '0'
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: minitest
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
|
-
- -
|
87
|
+
- - "~>"
|
100
88
|
- !ruby/object:Gem::Version
|
101
|
-
version:
|
89
|
+
version: 5.2.3
|
102
90
|
type: :development
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
|
-
- -
|
94
|
+
- - "~>"
|
108
95
|
- !ruby/object:Gem::Version
|
109
|
-
version:
|
96
|
+
version: 5.2.3
|
110
97
|
description: Evaluate methods in Ruby as Javascript instead
|
111
98
|
email:
|
112
99
|
- lee@new-bamboo.co.uk
|
@@ -114,51 +101,47 @@ executables: []
|
|
114
101
|
extensions: []
|
115
102
|
extra_rdoc_files: []
|
116
103
|
files:
|
117
|
-
- .gitignore
|
118
|
-
- .ruby-version
|
104
|
+
- ".gitignore"
|
105
|
+
- ".ruby-version"
|
119
106
|
- Gemfile
|
120
107
|
- LICENSE
|
121
108
|
- README.md
|
122
109
|
- Rakefile
|
123
110
|
- lib/node_module.rb
|
111
|
+
- lib/node_module/compiled.rb
|
124
112
|
- lib/node_module/opal_js_context.rb
|
125
113
|
- lib/node_module/version.rb
|
126
114
|
- node_module.gemspec
|
115
|
+
- spec/lib/node_module/compiled_spec.rb
|
127
116
|
- spec/lib/node_module/opal_js_context_spec.rb
|
128
117
|
- spec/lib/node_module_spec.rb
|
129
118
|
- spec/spec_helper.rb
|
130
119
|
homepage: http://github.com/leemachin/node_module
|
131
120
|
licenses:
|
132
121
|
- MIT
|
122
|
+
metadata: {}
|
133
123
|
post_install_message:
|
134
124
|
rdoc_options: []
|
135
125
|
require_paths:
|
136
126
|
- lib
|
137
127
|
required_ruby_version: !ruby/object:Gem::Requirement
|
138
|
-
none: false
|
139
128
|
requirements:
|
140
|
-
- -
|
129
|
+
- - ">="
|
141
130
|
- !ruby/object:Gem::Version
|
142
131
|
version: '0'
|
143
|
-
segments:
|
144
|
-
- 0
|
145
|
-
hash: -2723743550254407902
|
146
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
|
-
none: false
|
148
133
|
requirements:
|
149
|
-
- -
|
134
|
+
- - ">="
|
150
135
|
- !ruby/object:Gem::Version
|
151
136
|
version: '0'
|
152
|
-
segments:
|
153
|
-
- 0
|
154
|
-
hash: -2723743550254407902
|
155
137
|
requirements: []
|
156
138
|
rubyforge_project:
|
157
|
-
rubygems_version:
|
139
|
+
rubygems_version: 2.2.0
|
158
140
|
signing_key:
|
159
|
-
specification_version:
|
141
|
+
specification_version: 4
|
160
142
|
summary: Get really close to the metal in Ruby
|
161
143
|
test_files:
|
144
|
+
- spec/lib/node_module/compiled_spec.rb
|
162
145
|
- spec/lib/node_module/opal_js_context_spec.rb
|
163
146
|
- spec/lib/node_module_spec.rb
|
164
147
|
- spec/spec_helper.rb
|