opal 0.5.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -2
  3. data/README.md +1 -1
  4. data/Rakefile +11 -8
  5. data/lib/opal.rb +1 -1
  6. data/lib/opal/version.rb +1 -1
  7. data/opal.gemspec +1 -1
  8. data/{corelib → opal/core}/array.rb +47 -40
  9. data/{corelib → opal/core}/basic_object.rb +4 -0
  10. data/{corelib → opal/core}/boolean.rb +2 -6
  11. data/{corelib → opal/core}/class.rb +0 -0
  12. data/{corelib → opal/core}/comparable.rb +0 -0
  13. data/{corelib → opal/core}/encoding.rb +0 -0
  14. data/{corelib → opal/core}/enumerable.rb +160 -38
  15. data/opal/core/enumerator.rb +416 -0
  16. data/{corelib → opal/core}/error.rb +0 -0
  17. data/{corelib → opal/core}/hash.rb +38 -48
  18. data/{corelib → opal/core}/io.rb +13 -9
  19. data/{corelib → opal/core}/kernel.rb +75 -49
  20. data/{corelib → opal/core}/main.rb +0 -0
  21. data/{corelib → opal/core}/match_data.rb +0 -4
  22. data/{corelib → opal/core}/method.rb +0 -0
  23. data/{corelib → opal/core}/module.rb +24 -3
  24. data/{corelib → opal/core}/nil_class.rb +0 -4
  25. data/{corelib → opal/core}/numeric.rb +3 -4
  26. data/{corelib → opal/core}/proc.rb +0 -4
  27. data/{corelib → opal/core}/range.rb +0 -0
  28. data/{corelib → opal/core}/regexp.rb +0 -4
  29. data/{corelib → opal/core}/runtime.js +0 -0
  30. data/{corelib → opal/core}/string.rb +4 -6
  31. data/{corelib → opal/core}/struct.rb +3 -21
  32. data/{corelib → opal/core}/time.rb +0 -4
  33. data/opal/opal.rb +121 -0
  34. data/spec/corelib/array/select_spec.rb +14 -0
  35. data/spec/filters/20.rb +4 -0
  36. data/spec/filters/bugs/enumerable.rb +1 -48
  37. data/spec/filters/unsupported/enumerator.rb +13 -0
  38. data/spec/opal/compiler/irb_spec.rb +1 -0
  39. data/spec/rubyspecs +1 -0
  40. data/spec/{corelib → stdlib}/native/alias_native_spec.rb +6 -4
  41. data/spec/{corelib → stdlib}/native/each_spec.rb +3 -1
  42. data/spec/{corelib → stdlib}/native/element_reference_spec.rb +3 -1
  43. data/spec/stdlib/native/ext_spec.rb +19 -0
  44. data/spec/{corelib → stdlib}/native/initialize_spec.rb +4 -4
  45. data/spec/{corelib → stdlib}/native/method_missing_spec.rb +13 -1
  46. data/spec/{corelib → stdlib}/native/new_spec.rb +3 -1
  47. data/stdlib/enumerator.rb +1 -0
  48. data/stdlib/json.rb +1 -1
  49. data/stdlib/native.rb +483 -0
  50. metadata +52 -47
  51. data/corelib/enumerator.rb +0 -55
  52. data/corelib/native.rb +0 -270
  53. data/corelib/opal.rb +0 -88
  54. data/spec/corelib/native/ext_spec.rb +0 -5
  55. data/spec/filters/bugs/enumerator.rb +0 -6
data/opal/opal.rb ADDED
@@ -0,0 +1,121 @@
1
+ require 'core/runtime'
2
+ require 'core/module'
3
+ require 'core/class'
4
+ require 'core/basic_object'
5
+ require 'core/kernel'
6
+ require 'core/nil_class'
7
+ require 'core/boolean'
8
+ require 'core/error'
9
+ require 'core/regexp'
10
+ require 'core/comparable'
11
+ require 'core/enumerable'
12
+ require 'core/enumerator'
13
+ require 'core/array'
14
+ require 'core/hash'
15
+ require 'core/string'
16
+ require 'core/match_data'
17
+ require 'core/encoding'
18
+ require 'core/numeric'
19
+ require 'core/proc'
20
+ require 'core/method'
21
+ require 'core/range'
22
+ require 'core/time'
23
+ require 'core/struct'
24
+ require 'core/io'
25
+ require 'core/main'
26
+ require 'native'
27
+
28
+ # regexp matches
29
+ $& = $~ = $` = $' = nil
30
+
31
+ # stub library path
32
+ $: = []
33
+ $" = []
34
+
35
+ # split lines
36
+ $/ = "\n"
37
+ $, = " "
38
+
39
+ ARGV = []
40
+ ARGF = Object.new
41
+ ENV = {}
42
+
43
+ $VERBOSE = false
44
+ $DEBUG = false
45
+ $SAFE = 0
46
+
47
+ RUBY_PLATFORM = 'opal'
48
+ RUBY_ENGINE = 'opal'
49
+ RUBY_VERSION = '1.9.3'
50
+ RUBY_ENGINE_VERSION = '0.5.2'
51
+ RUBY_RELEASE_DATE = '2013-11-11'
52
+
53
+ module Opal
54
+ def self.coerce_to(object, type, method)
55
+ return object if type === object
56
+
57
+ unless object.respond_to? method
58
+ raise TypeError, "no implicit conversion of #{object.class} into #{type}"
59
+ end
60
+
61
+ object.__send__ method
62
+ end
63
+
64
+ def self.coerce_to!(object, type, method)
65
+ coerced = coerce_to(object, type, method)
66
+
67
+ unless type === coerced
68
+ raise TypeError, "can't convert #{object.class} into #{type} (#{object.class}##{method} gives #{coerced.class}"
69
+ end
70
+
71
+ coerced
72
+ end
73
+
74
+ def self.try_convert(object, type, method)
75
+ return object if type === object
76
+
77
+ if object.respond_to? method
78
+ object.__send__ method
79
+ end
80
+ end
81
+
82
+ def self.compare(a, b)
83
+ compare = a <=> b
84
+
85
+ if `compare === nil`
86
+ raise ArgumentError, "comparison of #{a.class.name} with #{b.class.name} failed"
87
+ end
88
+
89
+ compare
90
+ end
91
+
92
+ def self.truthy?(value)
93
+ if value
94
+ true
95
+ else
96
+ false
97
+ end
98
+ end
99
+
100
+ def self.falsy?(value)
101
+ if value
102
+ false
103
+ else
104
+ true
105
+ end
106
+ end
107
+
108
+ def self.destructure(args)
109
+ %x{
110
+ if (args.length == 1) {
111
+ return args[0];
112
+ }
113
+ else if (args._isArray) {
114
+ return args;
115
+ }
116
+ else {
117
+ return $slice.call(args);
118
+ }
119
+ }
120
+ end
121
+ end
@@ -0,0 +1,14 @@
1
+ describe "Array#select" do
2
+ it "passes an array item into a single default-block parameter" do
3
+ [["ABC", "DEF"]].select do |x|
4
+ x.should == ["ABC", "DEF"]
5
+ end
6
+ end
7
+
8
+ it "splits an array item into a list of default block parameters" do
9
+ [["ABC", "DEF"]].select do |x,y|
10
+ x.should == "ABC"
11
+ y.should == "DEF"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,4 @@
1
+ opal_filter "2.0 behaviour" do
2
+ fails "Enumerator.new ignores block if arg given"
3
+ fails "String#end_with? ignores arguments not convertible to string"
4
+ end
@@ -1,58 +1,11 @@
1
1
  opal_filter "Enumerable" do
2
- fails "Enumerable#drop passed a number n as an argument tries to convert n to an Integer using #to_int"
3
-
4
- fails "Enumerable#drop_while passes elements to the block until the first false"
5
-
6
- fails "Enumerable#each_slice raises an Argument Error if there is not a single parameter > 0"
7
-
8
- fails "Enumerable#each_with_index provides each element to the block"
9
- fails "Enumerable#each_with_index provides each element to the block and its index"
10
- fails "Enumerable#each_with_index binds splat arguments properly"
11
- fails "Enumerable#each_with_index passes extra parameters to each"
12
-
13
- fails "Enumerable#entries passes arguments to each"
14
-
15
- fails "Enumerable#first when passed an argument consumes only what is needed"
16
- fails "Enumerable#first when passed an argument raises a TypeError if the passed argument is not numeric"
17
- fails "Enumerable#first when passed an argument tries to convert the passed argument to an Integer using #to_int"
18
- fails "Enumerable#first when passed an argument raises an ArgumentError when count is negative"
2
+ fails "Enumerable#cycle passed a number n as an argument raises an ArgumentError if more arguments are passed"
19
3
 
20
4
  fails "Enumerable#grep can use $~ in the block when used with a Regexp"
21
5
 
22
- fails "Enumerable#group_by returns a hash without default_proc"
23
- fails "Enumerable#group_by gathers whole arrays as elements when each yields multiple"
24
-
25
- fails "Enumerable#include? returns true if any element == argument for numbers"
26
- fails "Enumerable#include? gathers whole arrays as elements when each yields multiple"
27
-
28
6
  fails "Enumerable#inject returns nil when fails(legacy rubycon)"
29
7
  fails "Enumerable#inject without inject arguments(legacy rubycon)"
30
- fails "Enumerable#inject can take a symbol argument"
31
- fails "Enumerable#inject ignores the block if two arguments"
32
- fails "Enumerable#inject can take two argument"
33
-
34
- fails "Enumerable#max raises an ArgumentError for incomparable elements"
35
- fails "Enumerable#max gathers whole arrays as elements when each yields multiple"
36
-
37
- fails "Enumerable#member? returns true if any element == argument for numbers"
38
- fails "Enumerable#member? gathers whole arrays as elements when each yields multiple"
39
-
40
- fails "Enumerable#min raises an ArgumentError for incomparable elements"
41
- fails "Enumerable#min gathers whole arrays as elements when each yields multiple"
42
8
 
43
9
  fails "Enumerable#reduce returns nil when fails(legacy rubycon)"
44
10
  fails "Enumerable#reduce without inject arguments(legacy rubycon)"
45
- fails "Enumerable#reduce can take a symbol argument"
46
- fails "Enumerable#reduce ignores the block if two arguments"
47
- fails "Enumerable#reduce can take two argument"
48
-
49
- fails "Enumerable#select passes through the values yielded by #each_with_index"
50
- fails "Enumerable#select returns an enumerator when no block given"
51
-
52
- fails "Enumerable#take when passed an argument consumes only what is needed"
53
- fails "Enumerable#take when passed an argument raises a TypeError if the passed argument is not numeric"
54
- fails "Enumerable#take when passed an argument tries to convert the passed argument to an Integer using #to_int"
55
- fails "Enumerable#take when passed an argument raises an ArgumentError when count is negative"
56
-
57
- fails "Enumerable#to_a passes arguments to each"
58
11
  end
@@ -0,0 +1,13 @@
1
+ opal_filter "Enumerator as generator" do
2
+ fails "Enumerator#next returns the next element of the enumeration"
3
+ fails "Enumerator#next raises a StopIteration exception at the end of the stream"
4
+ fails "Enumerator#next cannot be called again until the enumerator is rewound"
5
+
6
+ fails "Enumerator#rewind resets the enumerator to its initial state"
7
+ fails "Enumerator#rewind returns self"
8
+ fails "Enumerator#rewind has no effect on a new enumerator"
9
+ fails "Enumerator#rewind has no effect if called multiple, consecutive times"
10
+ fails "Enumerator#rewind does nothing if the object doesn't have a #rewind method"
11
+ fails "Enumerator#rewind works with peek to reset the position"
12
+ fails "Enumerator#rewind calls the enclosed object's rewind method if one exists"
13
+ end
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'native'
2
3
 
3
4
  describe Opal::Compiler do
4
5
  describe "irb parser option" do
data/spec/rubyspecs CHANGED
@@ -116,6 +116,7 @@ core/nil/xor_spec
116
116
 
117
117
  core/enumerable/all_spec
118
118
  core/enumerable/any_spec
119
+ core/enumerable/cycle_spec
119
120
  core/enumerable/collect_spec
120
121
  core/enumerable/count_spec
121
122
  core/enumerable/detect_spec
@@ -1,7 +1,9 @@
1
- describe "Native::Base.alias_native" do
1
+ require 'native'
2
+
3
+ describe "Native.alias_native" do
2
4
  it "refers to an attribute on @native" do
3
5
  Class.new {
4
- include Native::Base
6
+ include Native
5
7
 
6
8
  alias_native :a, :a
7
9
  }.new(`{ a: 2 }`).a.should == 2
@@ -9,7 +11,7 @@ describe "Native::Base.alias_native" do
9
11
 
10
12
  it "refers to an attribute on @native and calls it if it's a function" do
11
13
  Class.new {
12
- include Native::Base
14
+ include Native
13
15
 
14
16
  alias_native :a, :a
15
17
  }.new(`{ a: function() { return 42; } }`).a.should == 42
@@ -17,7 +19,7 @@ describe "Native::Base.alias_native" do
17
19
 
18
20
  it "defaults old to new" do
19
21
  Class.new {
20
- include Native::Base
22
+ include Native
21
23
 
22
24
  alias_native :a
23
25
  }.new(`{ a: 42 }`).a.should == 42
@@ -1,4 +1,6 @@
1
- describe "Native#each" do
1
+ require 'native'
2
+
3
+ describe "Native::Object#each" do
2
4
  it "enumerates on object properties" do
3
5
  Native(`{ a: 2, b: 3 }`).each {|name, value|
4
6
  ((name == :a && value == 2) || (name == :b && value == 3)).should be_true
@@ -1,4 +1,6 @@
1
- describe "Native#[]" do
1
+ require 'native'
2
+
3
+ describe "Native::Object#[]" do
2
4
  it "should return the same value for bridged classes" do
3
5
  Native(`2`).should === 2
4
6
  Native(`"lol"`).should === "lol"
@@ -0,0 +1,19 @@
1
+ require 'native'
2
+
3
+ describe Hash do
4
+ describe '#initialize' do
5
+ it "returns a hash with a nil value" do
6
+ h = Hash.new(`{a: null}`)
7
+ h[:a].should == nil
8
+ end
9
+ end
10
+
11
+ describe '#to_n' do
12
+ it "should return a js object representing hash" do
13
+ Hash.new({:a => 100, :b => 200}.to_n).should == {:a => 100, :b => 200}
14
+ end
15
+ end
16
+ end
17
+
18
+ describe "Hash#to_n" do
19
+ end
@@ -1,17 +1,17 @@
1
1
  require 'native'
2
2
 
3
- describe "Native::Base#initialize" do
4
- it "works when Native::Base is included in a BasicObject" do
3
+ describe "Native#initialize" do
4
+ it "works when Native is included in a BasicObject" do
5
5
  basic_class = Class.new(BasicObject)
6
6
  basic_object = basic_class.new
7
7
  lambda { basic_object.native? }.should raise_error(NoMethodError)
8
8
 
9
- basic_class.send :include, Native::Base
9
+ basic_class.send :include, Native
10
10
  lambda { basic_class.new(`{}`) }.should_not raise_error
11
11
  end
12
12
 
13
13
  it "detects a non native object" do
14
14
  object = Object.new
15
- lambda { Native.new(object) }.should raise_error(ArgumentError)
15
+ lambda { Native::Object.new(object) }.should raise_error(ArgumentError)
16
16
  end
17
17
  end
@@ -1,4 +1,6 @@
1
- describe "Native#method_missing" do
1
+ require 'native'
2
+
3
+ describe "Native::Object#method_missing" do
2
4
  it "should return values" do
3
5
  Native(`{ a: 23 }`).a.should == 23
4
6
  Native(`{ a: { b: 42 } }`).a.b.should == 42
@@ -36,4 +38,14 @@ describe "Native#method_missing" do
36
38
  it "should pass the block as function" do
37
39
  Native(`{ a: function(func) { return func(); } }`).a { 42 }.should == 42
38
40
  end
41
+
42
+ it "should unwrap arguments" do
43
+ x = `{}`
44
+
45
+ Native(`{ a: function(a, b) { return a === b } }`).a(Native(x), x).should == true
46
+ end
47
+
48
+ it "should wrap result" do
49
+ Native(`{ a: function() { return {}; } }`).a.class.should == Native::Object
50
+ end
39
51
  end
@@ -1,4 +1,6 @@
1
- describe "Native.new" do
1
+ require 'native'
2
+
3
+ describe "Native()" do
2
4
  it "should return nil for null or undefined" do
3
5
  Native(`null`).should be_nil
4
6
  Native(`undefined`).should be_nil
@@ -0,0 +1 @@
1
+ # stub
data/stdlib/json.rb CHANGED
@@ -78,7 +78,7 @@ module JSON
78
78
  options[:object_class] ||= Hash
79
79
  options[:array_class] ||= Array
80
80
 
81
- `to_opal(js_object, #{options.to_n})`
81
+ `to_opal(js_object, options.map)`
82
82
  end
83
83
 
84
84
  def self.generate(obj, options = {})
data/stdlib/native.rb ADDED
@@ -0,0 +1,483 @@
1
+ module Kernel
2
+ def native?(value)
3
+ `value == null || !value._klass`
4
+ end
5
+
6
+ def Native(obj)
7
+ if `#{obj} == null`
8
+ nil
9
+ elsif native?(obj)
10
+ Native::Object.new(obj)
11
+ else
12
+ obj
13
+ end
14
+ end
15
+
16
+ def Array(object, *args, &block)
17
+ %x{
18
+ if (object == null || object === nil) {
19
+ return [];
20
+ }
21
+ else if (#{native?(object)}) {
22
+ return #{Native::Array.new(object, *args, &block).to_a};
23
+ }
24
+ else if (#{object.respond_to? :to_ary}) {
25
+ return #{object.to_ary};
26
+ }
27
+ else if (#{object.respond_to? :to_a}) {
28
+ return #{object.to_a};
29
+ }
30
+ else {
31
+ return [object];
32
+ }
33
+ }
34
+ end
35
+ end
36
+
37
+ module Native
38
+ def self.is_a?(object, klass)
39
+ %x{
40
+ try {
41
+ return #{object} instanceof #{Native.try_convert(klass)};
42
+ }
43
+ catch (e) {
44
+ return false;
45
+ }
46
+ }
47
+ end
48
+
49
+ def self.try_convert(value)
50
+ %x{
51
+ if (#{native?(value)}) {
52
+ return #{value};
53
+ }
54
+ else if (#{value.respond_to? :to_n}) {
55
+ return #{value.to_n};
56
+ }
57
+ else {
58
+ return nil;
59
+ }
60
+ }
61
+ end
62
+
63
+ def self.convert(value)
64
+ native = try_convert(value)
65
+
66
+ if `#{native} === nil`
67
+ raise ArgumentError, "the passed value isn't a native"
68
+ end
69
+
70
+ native
71
+ end
72
+
73
+ def self.call(obj, key, *args, &block)
74
+ %x{
75
+ var prop = #{obj}[#{key}];
76
+
77
+ if (prop == null) {
78
+ return nil;
79
+ }
80
+ else if (prop instanceof Function) {
81
+ if (block !== nil) {
82
+ args.push(block);
83
+ }
84
+
85
+ args = #{args.map {|value|
86
+ native = try_convert(value)
87
+
88
+ if nil === native
89
+ value
90
+ else
91
+ native
92
+ end
93
+ }};
94
+
95
+ return #{Native(`prop.apply(#{obj}, #{args})`)};
96
+ }
97
+ else if (#{native?(`prop`)}) {
98
+ return #{Native(`prop`)};
99
+ }
100
+ else {
101
+ return prop;
102
+ }
103
+ }
104
+ end
105
+
106
+ module Helpers
107
+ def alias_native(new, old = new, options = {})
108
+ if old.end_with? ?=
109
+ define_method new do |value|
110
+ `#@native[#{old[0 .. -2]}] = #{Native.convert(value)}`
111
+
112
+ value
113
+ end
114
+ else
115
+ if as = options[:as]
116
+ define_method new do |*args, &block|
117
+ if value = Native.call(@native, old, *args, &block)
118
+ as.new(value.to_n)
119
+ end
120
+ end
121
+ else
122
+ define_method new do |*args, &block|
123
+ Native.call(@native, old, *args, &block)
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ def self.included(klass)
131
+ klass.extend Helpers
132
+ end
133
+
134
+ def initialize(native)
135
+ unless Kernel.native?(native)
136
+ Kernel.raise ArgumentError, "the passed value isn't native"
137
+ end
138
+
139
+ @native = native
140
+ end
141
+
142
+ def to_n
143
+ @native
144
+ end
145
+
146
+ class Object < BasicObject
147
+ include Native
148
+
149
+ def ==(other)
150
+ `#@native === #{Native.try_convert(other)}`
151
+ end
152
+
153
+ def has_key?(name)
154
+ `#@native.hasOwnProperty(#{name})`
155
+ end
156
+
157
+ alias key? has_key?
158
+ alias include? has_key?
159
+ alias member? has_key?
160
+
161
+ def each(*args)
162
+ if block_given?
163
+ %x{
164
+ for (var key in #@native) {
165
+ #{yield `key`, `#@native[key]`}
166
+ }
167
+ }
168
+
169
+ self
170
+ else
171
+ method_missing(:each, *args)
172
+ end
173
+ end
174
+
175
+ def [](key)
176
+ %x{
177
+ var prop = #@native[key];
178
+
179
+ if (prop instanceof Function) {
180
+ return prop;
181
+ }
182
+ else {
183
+ return #{::Native.call(@native, key)}
184
+ }
185
+ }
186
+ end
187
+
188
+ def []=(key, value)
189
+ native = Native.try_convert(value)
190
+
191
+ if `#{native} === nil`
192
+ `#@native[key] = #{value}`
193
+ else
194
+ `#@native[key] = #{native}`
195
+ end
196
+ end
197
+
198
+ def method_missing(mid, *args, &block)
199
+ %x{
200
+ if (mid.charAt(mid.length - 1) === '=') {
201
+ return #{self[mid.slice(0, mid.length - 1)] = args[0]};
202
+ }
203
+ else {
204
+ return #{::Native.call(@native, mid, *args, &block)};
205
+ }
206
+ }
207
+ end
208
+
209
+ def nil?
210
+ false
211
+ end
212
+
213
+ def is_a?(klass)
214
+ klass == Native
215
+ end
216
+
217
+ alias kind_of? is_a?
218
+
219
+ def instance_of?(klass)
220
+ klass == Native
221
+ end
222
+
223
+ def class
224
+ `self._klass`
225
+ end
226
+
227
+ def to_a(options = {}, &block)
228
+ Native::Array.new(@native, options, &block).to_a
229
+ end
230
+
231
+ def to_ary(options = {}, &block)
232
+ Native::Array.new(@native, options, &block)
233
+ end
234
+
235
+ def inspect
236
+ "#<Native:#{`String(#@native)`}>"
237
+ end
238
+ end
239
+
240
+ class Array
241
+ include Native
242
+ include Enumerable
243
+
244
+ def initialize(native, options = {}, &block)
245
+ super(native)
246
+
247
+ @get = options[:get] || options[:access]
248
+ @named = options[:named]
249
+ @set = options[:set] || options[:access]
250
+ @length = options[:length] || :length
251
+ @block = block
252
+
253
+ if `#{length} == null`
254
+ raise ArgumentError, "no length found on the array-like object"
255
+ end
256
+ end
257
+
258
+ def each(&block)
259
+ return enum_for :each unless block
260
+
261
+ index = 0
262
+ length = self.length
263
+
264
+ while index < length
265
+ block.call(self[index])
266
+
267
+ index += 1
268
+ end
269
+
270
+ self
271
+ end
272
+
273
+ def [](index)
274
+ result = case index
275
+ when String, Symbol
276
+ @named ? `#@native[#@named](#{index})` : `#@native[#{index}]`
277
+
278
+ when Integer
279
+ @get ? `#@native[#@get](#{index})` : `#@native[#{index}]`
280
+ end
281
+
282
+ if result
283
+ if @block
284
+ @block.call(result)
285
+ else
286
+ Native(result)
287
+ end
288
+ end
289
+ end
290
+
291
+ def []=(index, value)
292
+ if @set
293
+ `#@native[#@set](#{index}, #{value})`
294
+ else
295
+ `#@native[#{index}] = #{value}`
296
+ end
297
+ end
298
+
299
+ def last(count = nil)
300
+ if count
301
+ index = length - 1
302
+ result = []
303
+
304
+ while index >= 0
305
+ result << self[index]
306
+ index -= 1
307
+ end
308
+
309
+ result
310
+ else
311
+ self[length - 1]
312
+ end
313
+ end
314
+
315
+ def length
316
+ `#@native[#@length]`
317
+ end
318
+
319
+ def to_ary
320
+ self
321
+ end
322
+
323
+ def inspect
324
+ to_a.inspect
325
+ end
326
+ end
327
+ end
328
+
329
+ class Numeric
330
+ def to_n
331
+ `self.valueOf()`
332
+ end
333
+ end
334
+
335
+ class Proc
336
+ def to_n
337
+ self
338
+ end
339
+ end
340
+
341
+ class String
342
+ def to_n
343
+ `self.valueOf()`
344
+ end
345
+ end
346
+
347
+ class Regexp
348
+ def to_n
349
+ `self.valueOf()`
350
+ end
351
+ end
352
+
353
+ class MatchData
354
+ def to_n
355
+ @matches
356
+ end
357
+ end
358
+
359
+ class Struct
360
+ def initialize(*args)
361
+ if args.length == 1 && native?(args[0])
362
+ object = args[0]
363
+
364
+ members.each {|name|
365
+ instance_variable_set "@#{name}", Native(`#{object}[#{name}]`)
366
+ }
367
+ else
368
+ members.each_with_index {|name, index|
369
+ instance_variable_set "@#{name}", args[index]
370
+ }
371
+ end
372
+ end
373
+
374
+ def to_n
375
+ result = `{}`
376
+
377
+ each_pair {|name, value|
378
+ `#{result}[#{name}] = #{value.to_n}`
379
+ }
380
+
381
+ result
382
+ end
383
+ end
384
+
385
+ class Array
386
+ def to_n
387
+ %x{
388
+ var result = [];
389
+
390
+ for (var i = 0, length = self.length; i < length; i++) {
391
+ var obj = self[i];
392
+
393
+ if (#{`obj`.respond_to? :to_n}) {
394
+ result.push(#{`obj`.to_n});
395
+ }
396
+ else {
397
+ result.push(obj);
398
+ }
399
+ }
400
+
401
+ return result;
402
+ }
403
+ end
404
+ end
405
+
406
+ class Boolean
407
+ def to_n
408
+ `self.valueOf()`
409
+ end
410
+ end
411
+
412
+ class Time
413
+ def to_n
414
+ self
415
+ end
416
+ end
417
+
418
+ class NilClass
419
+ def to_n
420
+ `null`
421
+ end
422
+ end
423
+
424
+ class Hash
425
+ def initialize(defaults = undefined, &block)
426
+ %x{
427
+ if (defaults != null) {
428
+ if (defaults.constructor === Object) {
429
+ var map = self.map,
430
+ keys = self.keys;
431
+
432
+ for (var key in defaults) {
433
+ var value = defaults[key];
434
+
435
+ if (value && value.constructor === Object) {
436
+ map[key] = #{Hash.new(`value`)};
437
+ }
438
+ else {
439
+ map[key] = #{Native(`defaults[key]`)};
440
+ }
441
+
442
+ keys.push(key);
443
+ }
444
+ }
445
+ else {
446
+ self.none = defaults;
447
+ }
448
+ }
449
+ else if (block !== nil) {
450
+ self.proc = block;
451
+ }
452
+
453
+ return self;
454
+ }
455
+ end
456
+
457
+ def to_n
458
+ %x{
459
+ var result = {},
460
+ keys = self.keys,
461
+ map = self.map,
462
+ bucket,
463
+ value;
464
+
465
+ for (var i = 0, length = keys.length; i < length; i++) {
466
+ var key = keys[i],
467
+ obj = map[key];
468
+
469
+ if (#{`obj`.respond_to? :to_n}) {
470
+ result[key] = #{`obj`.to_n};
471
+ }
472
+ else {
473
+ result[key] = obj;
474
+ }
475
+ }
476
+
477
+ return result;
478
+ }
479
+ end
480
+ end
481
+
482
+ # native global
483
+ $$ = $global = Native(`Opal.global`)