node_module 0.1.4 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -1 +1 @@
1
- 1.9.3
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 javascript instead of Ruby.
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 javascript
59
+ # run a specific method as JavaScript
61
60
  node_module :meaning_of_life
62
61
 
63
- # run everything after this point as javascript
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
- methods Ruby gives you. You can pass in specific methods as symbols,
74
- or call it without any arguments to change every subsequently
75
- defined method.
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
- - Sharing state between methods or across a class is unpredictable,
82
- and will probably cause bad things to happen.
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
 
@@ -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(base)
10
- base.extend ClassMethods
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.execute_following_methods_as_javascript!(self)
22
+ NodeModule.compile_on_callback(self)
21
23
  else
22
- NodeModule.execute_methods_as_javascript!(methods, self)
24
+ NodeModule.compile_and_replace!(self, methods)
23
25
  end
24
26
  end
25
27
  end
26
28
 
27
- module_function
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
- NodeModule.opal_js_context.compile(meth)
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.execute_following_methods_as_javascript!(receiver)
37
+ def self.compile_on_callback(receiver)
42
38
  active = nil
43
- receiver.define_singleton_method(:method_added) do |meth_name|
39
+ receiver.define_singleton_method(:method_added) do |name|
44
40
  return if active
45
41
  active = true
46
- receiver.node_module(meth_name)
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
@@ -11,7 +11,7 @@ class NodeModule::OpalJsContext < V8::Context
11
11
  end
12
12
 
13
13
  def compile(code)
14
- eval Opal.parse(code)
14
+ eval Opal.compile(code)
15
15
  end
16
16
 
17
17
  def run(name, args=[])
@@ -1,3 +1,3 @@
1
1
  module NodeModule
2
- VERSION = "0.1.4"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -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.4
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: 2013-08-19 00:00:00.000000000 Z
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: '0'
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: '0'
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: 1.8.23
139
+ rubygems_version: 2.2.0
158
140
  signing_key:
159
- specification_version: 3
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