opal-native 0.0.2 → 0.0.3

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.
data/README.md CHANGED
@@ -2,10 +2,10 @@ Opal support for automagical native bridging
2
2
  ============================================
3
3
 
4
4
  This gem gives to Opal a standard API to implement bridges to native objects and glue-less native
5
- access and usage with the 'Object()` helper function.
5
+ access and usage with the `Native()` helper function.
6
6
 
7
7
  ```ruby
8
- o = Object(`$opal`)
8
+ o = Native(`$opal`)
9
9
 
10
10
  o.global.console # this will access the global console object and return it
11
11
  o.global.console.log('wut') # this will call the log function on the console object
data/Rakefile CHANGED
@@ -10,9 +10,9 @@ task :build => :dependencies do
10
10
  Opal::Builder.new(files: 'lib', out: 'build/opal-native.js').build
11
11
  end
12
12
 
13
- desc 'Build latest opal-native ready for testing to build dir'
14
- task :test => :dependencies do
15
- Opal::Builder.new(files: %w[lib spec], debug: true, out: 'build/opal-native.test.js').build
13
+ desc 'Run specs in spec/'
14
+ task :test => :build do
15
+ Opal::Context.runner 'spec/**/*.rb'
16
16
  end
17
17
 
18
18
  task :default => :build
@@ -8,113 +8,21 @@
8
8
  # 0. You just DO WHAT THE FUCK YOU WANT TO.
9
9
  #++
10
10
 
11
- class Module
12
- %x{
13
- function define_attr_bridge (klass, target, name, getter, setter) {
14
- if (getter) {
15
- $opal.defn(klass, $opal.mid_to_jsid(name), function() {
16
- var real = target;
17
-
18
- if (#{Symbol == `target`}) {
19
- real = target[0] == '@' ? this[target.substr(1)] : this[$opal.mid_to_jsid(target)].apply(this);
20
- }
21
-
22
- var result = real[name];
23
-
24
- return result == null ? nil : result;
25
- });
26
- }
27
-
28
- if (setter) {
29
- $opal.defn(klass, $opal.mid_to_jsid(name + '='), function (block, val) {
30
- var real = target;
31
-
32
- if (#{Symbol === `target`}) {
33
- real = target[0] == '@' ? this[target.substr(1)] : this[$opal.mid_to_jsid(target)].apply(this);
34
- }
35
-
36
- return real[name] = val;
37
- });
38
- }
39
- }
40
- }
41
-
42
- def attr_accessor_bridge (target, *attrs)
43
- %x{
44
- for (var i = 0, length = attrs.length; i < length; i++) {
45
- define_attr_bridge(this, target, attrs[i], true, true);
46
- }
47
- }
48
-
49
- self
50
- end
51
-
52
- def attr_reader_bridge (target, *attrs)
53
- %x{
54
- for (var i = 0, length = attrs.length; i < length; i++) {
55
- define_attr_bridge(this, target, attrs[i], true, false);
56
- }
57
- }
58
-
59
- self
60
- end
61
-
62
- def attr_writer_bridge (target, *attrs)
63
- %x{
64
- for (var i = 0, length = attrs.length; i < length; i++) {
65
- define_attr_bridge(this, target, attrs[i], false, true);
66
- }
67
- }
68
-
69
- self
70
- end
71
-
72
- def attr_bridge (target, name, setter = false)
73
- `define_attr_bridge(this, target, name, true, setter)`
74
-
75
- self
76
- end
77
-
78
- def define_method_bridge (object, name, ali = nil)
79
- %x{
80
- var self = this;
81
-
82
- $opal.defn(self, $opal.mid_to_jsid(#{ali || name}), function () {
83
- var real = object;
84
-
85
- if (#{Symbol === object}) {
86
- real = object[0] == '@' ? self[object.substr(1)] : self[$opal.mid_to_jsid(object)].apply(self);
87
- }
88
-
89
- return real[name].apply(real, arguments);
90
- });
91
- }
92
-
93
- nil
11
+ module Native
12
+ def self.=== (other)
13
+ `#{other} == null || !#{other}.o$klass`
94
14
  end
95
- end
96
-
97
- module Kernel
98
- def define_singleton_method_bridge (object, name, ali = nil)
99
- %x{
100
- var self = this;
101
15
 
102
- $opal.defs(this, $opal.mid_to_jsid(#{ali || name}), function () {
103
- var real = object;
104
-
105
- if (#{Symbol === object}) {
106
- real = object[0] == '@' ? self[object.substr(1)] : self[$opal.mid_to_jsid(object)].apply(self);
107
- }
16
+ def self.send (object, name, *args, &block)
17
+ args << block if block
108
18
 
109
- return real[name].apply(real, arguments);
110
- });
19
+ args = args.map {|obj|
20
+ Native === obj ? obj : obj.to_native
111
21
  }
112
22
 
113
- nil
23
+ Kernel.Native(`object[name].apply(object, args)`)
114
24
  end
115
- end
116
25
 
117
- module Native
118
26
  def self.included (klass)
119
27
  class << klass
120
28
  def from_native (object)
@@ -134,10 +42,12 @@ module Native
134
42
  @native
135
43
  end
136
44
 
137
- def native_send (name, *args)
138
- return method_missing(name, *args) unless Opal.function? `#@native[name]`
45
+ def native_send (name, *args, &block)
46
+ unless Proc === `#@native[name]`
47
+ raise NoMethodError, "undefined method `#{name}` for #{`#@native.toString()`}"
48
+ end
139
49
 
140
- `#@native[name].apply(#@native, args)`
50
+ Native.send(@native, name, *args, &block)
141
51
  end
142
52
 
143
53
  alias __native_send__ native_send
@@ -153,32 +63,18 @@ class Native::Object
153
63
  update!
154
64
  end
155
65
 
156
- def update! (name = nil)
157
- unless name
158
- %x{
159
- for (var name in #@native) {
160
- #{update!(`name`)}
161
- }
162
- }
66
+ def [] (name)
67
+ Kernel.Native(`#@native[name]`)
68
+ end
163
69
 
164
- return
165
- end
70
+ def []= (name, value)
71
+ value = value.to_native unless Native === value
166
72
 
167
- if Opal.function? `#@native[name]`
168
- define_singleton_method_bridge @native, name
73
+ `#@native[name] = #{value}`
169
74
 
170
- if respond_to? "#{name}="
171
- singleton_class.undef_method "#{name}="
172
- end
173
- else
174
- define_singleton_method name do
175
- self[name]
176
- end
75
+ update!(name)
177
76
 
178
- define_singleton_method "#{name}=" do |value|
179
- self[name] = value
180
- end
181
- end
77
+ value
182
78
  end
183
79
 
184
80
  def each
@@ -186,7 +82,7 @@ class Native::Object
186
82
 
187
83
  %x{
188
84
  for (var name in #@native) {
189
- #{yield Kernel.Object(`name`), Kernel.Object(`#@native[name]`)}
85
+ #{yield Kernel.Native(`name`), Kernel.Native(`#@native[name]`)}
190
86
  }
191
87
  }
192
88
 
@@ -198,7 +94,7 @@ class Native::Object
198
94
 
199
95
  %x{
200
96
  for (var name in #@native) {
201
- #{yield Kernel.Object(`name`)}
97
+ #{yield Kernel.Native(`name`)}
202
98
  }
203
99
  }
204
100
 
@@ -210,33 +106,23 @@ class Native::Object
210
106
 
211
107
  %x{
212
108
  for (var name in #@native) {
213
- #{yield Kernel.Object(`#@native[name]`)}
109
+ #{yield Kernel.Native(`#@native[name]`)}
214
110
  }
215
111
  }
216
112
  end
217
113
 
218
- def [] (name)
219
- Kernel.Object(`#@native[name] || nil`)
114
+ def inspect
115
+ "#<Native: #{`#@native.toString()`}>"
220
116
  end
221
117
 
222
- def []= (name, value)
223
- value = value.to_native unless Opal.native?(value)
224
-
225
- `#@native[name] = #{value}`
226
-
227
- update!(name)
228
-
229
- value
118
+ def keys
119
+ each_key.to_a
230
120
  end
231
121
 
232
122
  def nil?
233
123
  `#@native === null || #@native === undefined`
234
124
  end
235
125
 
236
- def inspect
237
- "#<Native: #{`#@native.toString()`}>"
238
- end
239
-
240
126
  def to_s
241
127
  `#@native.toString()`
242
128
  end
@@ -244,11 +130,47 @@ class Native::Object
244
130
  def to_hash
245
131
  Hash[to_a]
246
132
  end
133
+
134
+ def values
135
+ each_value.to_a
136
+ end
137
+
138
+ def update! (name = nil)
139
+ unless name
140
+ %x{
141
+ for (var name in #@native) {
142
+ #{update!(`name`)}
143
+ }
144
+ }
145
+
146
+ return
147
+ end
148
+
149
+ if Proc === `#@native[name]`
150
+ define_singleton_method name do |*args, &block|
151
+ __native_send__(name, *args, &block)
152
+ end
153
+
154
+ if respond_to? "#{name}="
155
+ singleton_class.undef_method "#{name}="
156
+ end
157
+ else
158
+ define_singleton_method name do
159
+ self[name]
160
+ end
161
+
162
+ define_singleton_method "#{name}=" do |value|
163
+ self[name] = value
164
+ end
165
+ end
166
+ end
247
167
  end
248
168
 
249
169
  module Kernel
250
- def Object (object)
251
- Opal.native?(object) ? Native::Object.new(object) : object
170
+ def Native (object)
171
+ return if `object == null`
172
+
173
+ Native === object ? Native::Object.new(object) : object
252
174
  end
253
175
  end
254
176
 
@@ -266,7 +188,7 @@ end
266
188
 
267
189
  class Array
268
190
  def to_native
269
- map { |obj| Opal.object?(obj) ? obj.to_native : obj }
191
+ map { |obj| Native === obj ? obj : obj.to_native }
270
192
  end
271
193
  end
272
194
 
@@ -280,7 +202,7 @@ class Hash
280
202
  var key = map[assoc][0],
281
203
  value = map[assoc][1];
282
204
 
283
- result[key] = #{Opal.native?(`value`)} ? value : #{`value`.to_native};
205
+ result[key] = #{Native === `value` ? `value` : `value`.to_native};
284
206
  }
285
207
 
286
208
  return result;
@@ -310,7 +232,9 @@ class Proc
310
232
  var self = this;
311
233
 
312
234
  return (function () {
313
- return self.apply(self.$S, arguments);
235
+ return self.apply(self.$S, [null].concat(#{
236
+ `$slice.call(arguments)`.map { |o| Kernel.Native(o) }
237
+ }));
314
238
  });
315
239
  }
316
240
  end
@@ -327,3 +251,5 @@ class String
327
251
  `this.valueOf()`
328
252
  end
329
253
  end
254
+
255
+ require 'native/bridge'
@@ -0,0 +1,123 @@
1
+ #--
2
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
3
+ # Version 2, December 2004
4
+ #
5
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
6
+ # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
7
+ #
8
+ # 0. You just DO WHAT THE FUCK YOU WANT TO.
9
+ #++
10
+
11
+ class Module
12
+ def define_attr_bridge (target, name, getter, setter)
13
+ if getter
14
+ if Symbol === target
15
+ if target.start_with? '@'
16
+ define_method name do
17
+ object = instance_variable_get(target)
18
+
19
+ Kernel.Native(`#{Native === object ? object : object.to_native}[name]`)
20
+ end
21
+ else
22
+ define_method name do
23
+ object = __send__(target)
24
+
25
+ Kernel.Native(`#{Native === object ? object : object.to_native}[name]`)
26
+ end
27
+ end
28
+ else
29
+ define_method name do |*args, &block|
30
+ Kernel.Native(`target[name]`)
31
+ end
32
+ end
33
+ end
34
+
35
+ if setter
36
+ if Symbol === target
37
+ if target.start_with? '@'
38
+ define_method "#{name}=" do |value|
39
+ object = instance_variable_get(target)
40
+ value = value.to_native unless Native === value
41
+
42
+ Kernel.Native(`#{Native === object ? object : object.to_native}[name] = value`)
43
+ end
44
+ else
45
+ define_method "#{name}=" do |value|
46
+ object = __send__(target)
47
+ value = value.to_native unless Native === value
48
+
49
+ Kernel.Native(`#{Native === object ? object : object.to_native}[name] = value`)
50
+ end
51
+ end
52
+ else
53
+ define_method "#{name}=" do |value|
54
+ value = value.to_native unless Native === value
55
+
56
+ Kernel.Native(`target[name] = value`)
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ def attr_accessor_bridge (target, *attrs)
63
+ attrs.each {|attr|
64
+ define_attr_bridge(target, attr, true, true)
65
+ }
66
+
67
+ self
68
+ end
69
+
70
+ def attr_reader_bridge (target, *attrs)
71
+ attrs.each {|attr|
72
+ define_attr_bridge(target, attr, true, false)
73
+ }
74
+
75
+ self
76
+ end
77
+
78
+ def attr_writer_bridge (target, *attrs)
79
+ attrs.each { |attr|
80
+ define_attr_bridge(target, attr, false, true)
81
+ }
82
+
83
+ self
84
+ end
85
+
86
+ def attr_bridge (target, name, setter = false)
87
+ define_attr_bridge(target, name, true, setter)
88
+
89
+ self
90
+ end
91
+
92
+ def define_method_bridge (target, name, ali = nil)
93
+ if Symbol === target
94
+ if target.start_with? '@'
95
+ define_method ali || name do |*args, &block|
96
+ object = instance_variable_get(target)
97
+
98
+ Native.send(Native === object ? object : object.to_native, name, *args, &block)
99
+ end
100
+ else
101
+ define_method ali || name do |*args, &block|
102
+ object = __send__(target)
103
+
104
+ Native.send(Native === object ? object : object.to_native, name, *args, &block)
105
+ end
106
+ end
107
+ else
108
+ define_method ali || name do |*args, &block|
109
+ Native.send(target, name, *args, &block)
110
+ end
111
+ end
112
+
113
+ nil
114
+ end
115
+ end
116
+
117
+ module Kernel
118
+ def define_singleton_method_bridge (target, name, ali = nil)
119
+ define_singleton_method ali || name do |*args, &block|
120
+ Native.send(target, name, *args, &block)
121
+ end
122
+ end
123
+ end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new {|s|
2
2
  s.name = 'opal-native'
3
- s.version = '0.0.2'
3
+ s.version = '0.0.3'
4
4
  s.author = 'meh.'
5
5
  s.email = 'meh@paranoici.org'
6
6
  s.homepage = 'http://github.com/opal/opal-native'
@@ -12,5 +12,5 @@ Gem::Specification.new {|s|
12
12
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
13
13
  s.require_paths = ['lib']
14
14
 
15
- s.add_development_dependency 'opal-spec'
15
+ # s.add_dependency 'opal-spec'
16
16
  }
@@ -0,0 +1,43 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe Native do
4
+ before do
5
+ @object = object = `{
6
+ a: 23,
7
+
8
+ b: function () {
9
+ return 1337;
10
+ }
11
+ }`
12
+
13
+ @test = Class.new {
14
+ attr_accessor_bridge object, :a
15
+
16
+ define_method_bridge object, :b
17
+
18
+ define_singleton_method_bridge object, :b, :c
19
+ }
20
+ end
21
+
22
+ it 'bridges correctly accessors' do
23
+ test = @test.new
24
+
25
+ `#@object.a`.should == 23
26
+ `#@object.a = 42`
27
+ `#@object.a`.should == 42
28
+
29
+ test.a.should == 42
30
+
31
+ test.a = 23
32
+ test.a.should == 23
33
+ `#@object.a`.should == 23
34
+ end
35
+
36
+ it 'bridges correctly methods' do
37
+ @test.new.b.should == 1337
38
+ end
39
+
40
+ it 'bridges correctly singleton methods' do
41
+ @test.c.should == 1337
42
+ end
43
+ end
@@ -1,11 +1,17 @@
1
1
  require File.expand_path('../spec_helper', __FILE__)
2
2
 
3
- class Test
4
- include Native
5
- end
6
-
7
3
  describe Native do
4
+ before do
5
+ @test = Class.new {
6
+ include Native
7
+ }
8
+ end
9
+
8
10
  it 'creates a working object' do
9
- Test.new(42).to_native.should == 42
11
+ @test.new(42).to_native.should == 42
12
+ end
13
+
14
+ it 'sends calls properly' do
15
+ @test.new(42).native_send(:toString, 16).should == '2a'
10
16
  end
11
17
  end
@@ -0,0 +1,46 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe Native::Object do
4
+ before do
5
+ @object = `{
6
+ a: 42,
7
+
8
+ b: function () {
9
+ return 42;
10
+ },
11
+
12
+ c: function () {
13
+ return { a: 23 };
14
+ },
15
+
16
+ d: function (a, h) {
17
+ return h({a: a});
18
+ }
19
+ }`
20
+
21
+ @test = Kernel.Native(@object)
22
+ end
23
+
24
+ it 'wraps an object properly' do
25
+ `#{@test.to_native} == #{@object}`.should be_true
26
+ end
27
+
28
+ it 'makes an accessor properly' do
29
+ @test.a.should == 42
30
+ @test.a = 23
31
+ @test.a.should == 23
32
+ `#@object.a`.should == 23
33
+ end
34
+
35
+ it 'calls a function as a method when present' do
36
+ @test.b.should == 42
37
+ end
38
+
39
+ it 'calls a function as a method when present and returns a Native' do
40
+ @test.c.a.should == 23
41
+ end
42
+
43
+ it 'calls handlers with proper wrapping' do
44
+ @test.d(23) { |o| o.a }.should == 23
45
+ end
46
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opal-native
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,19 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-18 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: opal-spec
16
- requirement: &15880980 !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :development
23
- prerelease: false
24
- version_requirements: *15880980
12
+ date: 2012-01-21 00:00:00.000000000 Z
13
+ dependencies: []
25
14
  description:
26
15
  email: meh@paranoici.org
27
16
  executables: []
@@ -32,8 +21,11 @@ files:
32
21
  - README.md
33
22
  - Rakefile
34
23
  - lib/opal/native.rb
24
+ - lib/opal/native/bridge.rb
35
25
  - opal-native.gemspec
26
+ - spec/bridge_spec.rb
36
27
  - spec/native_spec.rb
28
+ - spec/object_spec.rb
37
29
  - spec/spec_helper.rb
38
30
  - spec/spec_runner.html
39
31
  homepage: http://github.com/opal/opal-native
@@ -61,6 +53,8 @@ signing_key:
61
53
  specification_version: 3
62
54
  summary: Easy support for native objects in Opal
63
55
  test_files:
56
+ - spec/bridge_spec.rb
64
57
  - spec/native_spec.rb
58
+ - spec/object_spec.rb
65
59
  - spec/spec_helper.rb
66
60
  - spec/spec_runner.html