opal-native 0.0.1.2 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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