opal-native 0.0.1.2 → 0.0.2

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.
@@ -0,0 +1,18 @@
1
+ Opal support for automagical native bridging
2
+ ============================================
3
+
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.
6
+
7
+ ```ruby
8
+ o = Object(`$opal`)
9
+
10
+ o.global.console # this will access the global console object and return it
11
+ o.global.console.log('wut') # this will call the log function on the console object
12
+
13
+ o.to_hash # this will return the object's properties as a Hash
14
+ # you can also treat the object as an Enumerable
15
+
16
+ # keep in mind that when using the `.` syntax if the property is a function, it will be called
17
+ # if you want the value of the function you have to use `#[]` or `#[]=`.
18
+ ```
data/Rakefile CHANGED
@@ -1,4 +1,3 @@
1
- require 'bundler/setup'
2
1
  require 'opal'
3
2
 
4
3
  desc 'Build specified dependencies to build dir'
@@ -7,8 +6,13 @@ task :dependencies do
7
6
  end
8
7
 
9
8
  desc 'Build latest opal-native to build dir'
10
- task :build do
11
- Opal::Builder.new('lib', join: 'build/opal-native.js').build
9
+ task :build => :dependencies do
10
+ Opal::Builder.new(files: 'lib', out: 'build/opal-native.js').build
11
+ end
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
12
16
  end
13
17
 
14
18
  task :default => :build
@@ -8,29 +8,113 @@
8
8
  # 0. You just DO WHAT THE FUCK YOU WANT TO.
9
9
  #++
10
10
 
11
- module Native
12
- class Object
13
- include Native
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;
14
17
 
15
- def [](name)
16
- `#@native[name]`
17
- end
18
+ if (#{Symbol == `target`}) {
19
+ real = target[0] == '@' ? this[target.substr(1)] : this[$opal.mid_to_jsid(target)].apply(this);
20
+ }
18
21
 
19
- def []=(name, value)
20
- `#@native[name] = value`
21
- end
22
+ var result = real[name];
22
23
 
23
- def nil?
24
- `#@native === null || #@native === undefined`
25
- end
24
+ return result == null ? nil : result;
25
+ });
26
+ }
26
27
 
27
- def method_missing (name, *args)
28
- return super unless Opal.function? `#@native[name]`
28
+ if (setter) {
29
+ $opal.defn(klass, $opal.mid_to_jsid(name + '='), function (block, val) {
30
+ var real = target;
29
31
 
30
- __native_send__ name, *args
31
- end
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
32
50
  end
33
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
94
+ end
95
+ end
96
+
97
+ module Kernel
98
+ def define_singleton_method_bridge (object, name, ali = nil)
99
+ %x{
100
+ var self = this;
101
+
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
+ }
108
+
109
+ return real[name].apply(real, arguments);
110
+ });
111
+ }
112
+
113
+ nil
114
+ end
115
+ end
116
+
117
+ module Native
34
118
  def self.included (klass)
35
119
  class << klass
36
120
  def from_native (object)
@@ -56,94 +140,115 @@ module Native
56
140
  `#@native[name].apply(#@native, args)`
57
141
  end
58
142
 
59
- alias_method :__native_send__, :native_send
143
+ alias __native_send__ native_send
60
144
  end
61
145
 
62
- class Module
63
- %x{
64
- function define_attr_bridge(klass, target, name, getter, setter) {
65
- if (getter) {
66
- $opal.defn(klass, $opal.mid_to_jsid(name), function() {
67
- var real_target = target;
146
+ class Native::Object
147
+ include Native
148
+ include Enumerable
68
149
 
69
- if (target.$f & T_STRING) {
70
- real_target = target[0] == '@' ? this[target.substr(1)] : this[$opal.mid_to_jsid(target)].apply(this, null);
71
- }
150
+ def initialize (*)
151
+ super
72
152
 
73
- var result = real_target[name];
153
+ update!
154
+ end
74
155
 
75
- return result == null ? nil : result;
76
- });
156
+ def update! (name = nil)
157
+ unless name
158
+ %x{
159
+ for (var name in #@native) {
160
+ #{update!(`name`)}
161
+ }
77
162
  }
78
163
 
79
- if (setter) {
80
- $opal.defn(klass, $opal.mid_to_jsid(name + '='), function (block, val) {
81
- var real_target = target;
164
+ return
165
+ end
82
166
 
83
- if (target.$f & T_STRING) {
84
- real_target = target[0] == '@' ? this[target.substr(1)] : this[$opal.mid_to_jsid(target)].apply(this, null);
85
- }
167
+ if Opal.function? `#@native[name]`
168
+ define_singleton_method_bridge @native, name
86
169
 
87
- return real_target[name] = val;
88
- });
89
- }
90
- }
91
- }
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
177
+
178
+ define_singleton_method "#{name}=" do |value|
179
+ self[name] = value
180
+ end
181
+ end
182
+ end
183
+
184
+ def each
185
+ return enum_for :each unless block_given?
92
186
 
93
- def attr_accessor_bridge(target, *attrs)
94
187
  %x{
95
- for (var i = 0, length = attrs.length; i < length; i++) {
96
- define_attr_bridge(this, target, attrs[i], true, true);
188
+ for (var name in #@native) {
189
+ #{yield Kernel.Object(`name`), Kernel.Object(`#@native[name]`)}
97
190
  }
98
191
  }
99
192
 
100
193
  self
101
194
  end
102
195
 
103
- def attr_reader_bridge(target, *attrs)
196
+ def each_key
197
+ return enum_for :each_key unless block_given?
198
+
104
199
  %x{
105
- for (var i = 0, length = attrs.length; i < length; i++) {
106
- define_attr_bridge(this, target, attrs[i], true, false);
200
+ for (var name in #@native) {
201
+ #{yield Kernel.Object(`name`)}
107
202
  }
108
203
  }
109
204
 
110
205
  self
111
206
  end
112
207
 
113
- def attr_reader_bridge(target, *attrs)
208
+ def each_value
209
+ return enum_for :each_value unless block_given?
210
+
114
211
  %x{
115
- for (var i = 0, length = attrs.length; i < length; i++) {
116
- define_attr_bridge(this, target, attrs[i], false, true);
212
+ for (var name in #@native) {
213
+ #{yield Kernel.Object(`#@native[name]`)}
117
214
  }
118
215
  }
216
+ end
119
217
 
120
- self
218
+ def [] (name)
219
+ Kernel.Object(`#@native[name] || nil`)
121
220
  end
122
221
 
123
- def attr_bridge(target, name, setter = false)
124
- `define_attr_bridge(this, target, name, true, setter)`
222
+ def []= (name, value)
223
+ value = value.to_native unless Opal.native?(value)
125
224
 
126
- self
225
+ `#@native[name] = #{value}`
226
+
227
+ update!(name)
228
+
229
+ value
127
230
  end
128
231
 
129
- %x{
130
- function define_method_bridge(klass, target, id, name) {
131
- define_method(klass, id, function() {
132
- var real_target = target;
232
+ def nil?
233
+ `#@native === null || #@native === undefined`
234
+ end
133
235
 
134
- if (target.$f & T_STRING) {
135
- real_target = target[0] == '@' ? this[target.substr(1)] : this[$opal.mid_to_jsid(target)].apply(this, null);
136
- }
236
+ def inspect
237
+ "#<Native: #{`#@native.toString()`}>"
238
+ end
137
239
 
138
- return real_target.apply(this, $slice.call(arguments, 1));
139
- });
140
- }
141
- }
240
+ def to_s
241
+ `#@native.toString()`
242
+ end
142
243
 
143
- def define_method_bridge(object, name, ali = nil)
144
- `define_method_bridge(this, object, $opal.mid_to_jsid(#{ali || name}), name)`
244
+ def to_hash
245
+ Hash[to_a]
246
+ end
247
+ end
145
248
 
146
- self
249
+ module Kernel
250
+ def Object (object)
251
+ Opal.native?(object) ? Native::Object.new(object) : object
147
252
  end
148
253
  end
149
254
 
@@ -188,8 +293,8 @@ class MatchData
188
293
  end
189
294
 
190
295
  class NilClass
191
- def to_native
192
- `var result; return result;`
296
+ def to_native (result = undefined)
297
+ result
193
298
  end
194
299
  end
195
300
 
@@ -202,16 +307,18 @@ end
202
307
  class Proc
203
308
  def to_native
204
309
  %x{
205
- return function () {
206
- return this.apply(this.$S, arguments);
207
- };
310
+ var self = this;
311
+
312
+ return (function () {
313
+ return self.apply(self.$S, arguments);
314
+ });
208
315
  }
209
316
  end
210
317
  end
211
318
 
212
319
  class Regexp
213
320
  def to_native
214
- self
321
+ `this.valueOf()`
215
322
  end
216
323
  end
217
324
 
@@ -220,9 +327,3 @@ class String
220
327
  `this.valueOf()`
221
328
  end
222
329
  end
223
-
224
- module Kernel
225
- def Object(object)
226
- Opal.native?(object) ? Native::Object.new(object) : object
227
- end
228
- end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new {|s|
2
2
  s.name = 'opal-native'
3
- s.version = '0.0.1.2'
3
+ s.version = '0.0.2'
4
4
  s.author = 'meh.'
5
5
  s.email = 'meh@paranoici.org'
6
6
  s.homepage = 'http://github.com/opal/opal-native'
@@ -11,4 +11,6 @@ Gem::Specification.new {|s|
11
11
  s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
12
12
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
13
13
  s.require_paths = ['lib']
14
+
15
+ s.add_development_dependency 'opal-spec'
14
16
  }
@@ -0,0 +1,11 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ class Test
4
+ include Native
5
+ end
6
+
7
+ describe Native do
8
+ it 'creates a working object' do
9
+ Test.new(42).to_native.should == 42
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ require 'opal/spec/autorun'
2
+ require 'native'
3
+
4
+ if $0 == __FILE__
5
+ Dir['spec/**/*.rb'].each { |spec| require spec }
6
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
+
6
+ <title>Spec_runner</title>
7
+
8
+ <script src="../build/opal.debug.js" type="text/javascript" charset="utf-8"></script>
9
+ <script src="../build/opal-spec.debug.js" type="text/javascript" charset="utf-8"></script>
10
+ <script src="../build/opal-native.test.debug.js" type="text/javascript" charset="utf-8"></script>
11
+ </head>
12
+
13
+ <body onload="opal.main('/spec/spec_helper.rb')">
14
+ </body>
15
+ </html>
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.1.2
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,19 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-12 00:00:00.000000000 Z
13
- dependencies: []
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
14
25
  description:
15
26
  email: meh@paranoici.org
16
27
  executables: []
@@ -18,9 +29,13 @@ extensions: []
18
29
  extra_rdoc_files: []
19
30
  files:
20
31
  - .gitignore
32
+ - README.md
21
33
  - Rakefile
22
34
  - lib/opal/native.rb
23
35
  - opal-native.gemspec
36
+ - spec/native_spec.rb
37
+ - spec/spec_helper.rb
38
+ - spec/spec_runner.html
24
39
  homepage: http://github.com/opal/opal-native
25
40
  licenses: []
26
41
  post_install_message:
@@ -45,4 +60,7 @@ rubygems_version: 1.8.10
45
60
  signing_key:
46
61
  specification_version: 3
47
62
  summary: Easy support for native objects in Opal
48
- test_files: []
63
+ test_files:
64
+ - spec/native_spec.rb
65
+ - spec/spec_helper.rb
66
+ - spec/spec_runner.html