opal 0.9.0.beta2 → 0.9.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.jshintrc +2 -1
  3. data/.travis.yml +8 -4
  4. data/CHANGELOG.md +270 -251
  5. data/CONTRIBUTING.md +41 -0
  6. data/README.md +8 -8
  7. data/Rakefile +1 -1
  8. data/lib/opal/cli.rb +1 -0
  9. data/lib/opal/cli_options.rb +2 -2
  10. data/lib/opal/cli_runners.rb +1 -0
  11. data/lib/opal/cli_runners/nashorn.rb +58 -0
  12. data/lib/opal/cli_runners/phantom.js +11 -9
  13. data/lib/opal/compiler.rb +2 -0
  14. data/lib/opal/erb.rb +2 -1
  15. data/lib/opal/nodes/def.rb +15 -6
  16. data/lib/opal/nodes/helpers.rb +1 -1
  17. data/lib/opal/nodes/literal.rb +1 -1
  18. data/lib/opal/nodes/masgn.rb +79 -29
  19. data/lib/opal/nodes/module.rb +1 -1
  20. data/lib/opal/nodes/top.rb +6 -2
  21. data/lib/opal/parser.rb +1 -0
  22. data/lib/opal/parser/grammar.rb +3160 -3083
  23. data/lib/opal/parser/grammar.y +39 -11
  24. data/lib/opal/parser/lexer.rb +15 -13
  25. data/lib/opal/parser/sexp.rb +5 -0
  26. data/lib/opal/version.rb +1 -1
  27. data/opal/corelib/array.rb +21 -6
  28. data/opal/corelib/basic_object.rb +17 -4
  29. data/opal/corelib/class.rb +1 -1
  30. data/opal/corelib/constants.rb +2 -2
  31. data/opal/corelib/enumerator.rb +2 -0
  32. data/opal/corelib/hash.rb +50 -50
  33. data/opal/corelib/helpers.rb +1 -1
  34. data/opal/corelib/io.rb +9 -6
  35. data/opal/corelib/kernel.rb +37 -9
  36. data/opal/corelib/module.rb +6 -17
  37. data/opal/corelib/nil.rb +4 -0
  38. data/opal/corelib/number.rb +0 -4
  39. data/opal/corelib/runtime.js +637 -662
  40. data/opal/corelib/struct.rb +7 -3
  41. data/spec/filters/bugs/array.rb +4 -9
  42. data/spec/filters/bugs/basicobject.rb +1 -15
  43. data/spec/filters/bugs/date.rb +4 -26
  44. data/spec/filters/bugs/enumerable.rb +26 -1
  45. data/spec/filters/bugs/enumerator.rb +4 -4
  46. data/spec/filters/bugs/exception.rb +1 -7
  47. data/spec/filters/bugs/float.rb +14 -0
  48. data/spec/filters/bugs/hash.rb +0 -2
  49. data/spec/filters/bugs/integer.rb +1 -1
  50. data/spec/filters/bugs/kernel.rb +47 -66
  51. data/spec/filters/bugs/language.rb +1 -2
  52. data/spec/filters/bugs/module.rb +11 -14
  53. data/spec/filters/bugs/numeric.rb +3 -3
  54. data/spec/filters/bugs/proc.rb +0 -1
  55. data/spec/filters/bugs/range.rb +2 -3
  56. data/spec/filters/bugs/regexp.rb +15 -17
  57. data/spec/filters/bugs/set.rb +2 -2
  58. data/spec/filters/bugs/string.rb +29 -5
  59. data/spec/filters/bugs/{strscan.rb → stringscanner.rb} +9 -10
  60. data/spec/filters/bugs/struct.rb +0 -4
  61. data/spec/filters/bugs/time.rb +2 -3
  62. data/spec/filters/bugs/unboundmethod.rb +3 -0
  63. data/spec/filters/unsupported/freeze.rb +2 -1
  64. data/spec/filters/unsupported/taint.rb +2 -0
  65. data/spec/lib/parser/aref_spec.rb +10 -0
  66. data/spec/lib/parser/lambda_spec.rb +14 -0
  67. data/spec/lib/parser/op_asgn_spec.rb +17 -0
  68. data/spec/lib/parser/return_spec.rb +5 -0
  69. data/spec/lib/parser/unary_spec.rb +4 -0
  70. data/spec/lib/sprockets/erb_spec.rb +1 -1
  71. data/spec/mspec/opal/formatters.rb +159 -0
  72. data/{lib → spec}/mspec/opal/runner.rb +0 -160
  73. data/spec/opal/core/hash/internals_spec.rb +162 -162
  74. data/spec/opal/core/kernel/at_exit_spec.rb +70 -0
  75. data/spec/opal/core/kernel/extend_spec.rb +1 -1
  76. data/spec/opal/core/kernel/instance_variables_spec.rb +56 -0
  77. data/spec/opal/core/language/equal_spec.rb +8 -0
  78. data/spec/opal/core/language/predefined_spec.rb +1 -1
  79. data/spec/opal/core/language/ternary_operator_spec.rb +14 -0
  80. data/spec/opal/core/language/versions/{hash_1.9.rb → hash_1_9_spec.rb} +5 -0
  81. data/spec/opal/core/module/fixtures/classes.rb +11 -1
  82. data/spec/opal/core/module/method_lookup_spec.rb +13 -0
  83. data/spec/opal/core/runtime/super_spec.rb +10 -0
  84. data/spec/opal/stdlib/native/new_spec.rb +84 -0
  85. data/spec/opal/stdlib/strscan/scan_spec.rb +11 -0
  86. data/spec/rubyspecs +6 -9
  87. data/spec/spec_helper.rb +9 -21
  88. data/stdlib/date.rb +121 -1
  89. data/stdlib/js.rb +13 -5
  90. data/stdlib/json.rb +3 -3
  91. data/stdlib/nashorn.rb +5 -0
  92. data/stdlib/nashorn/file.rb +13 -0
  93. data/stdlib/nashorn/io.rb +2 -0
  94. data/stdlib/native.rb +12 -4
  95. data/stdlib/nodejs/io.rb +5 -2
  96. data/stdlib/opal/platform.rb +19 -0
  97. data/stdlib/phantomjs.rb +4 -0
  98. data/stdlib/strscan.rb +1 -1
  99. data/tasks/building.rake +2 -1
  100. data/tasks/testing.rake +29 -34
  101. data/tasks/testing/{phantomjs1-sprockets.js → sprockets-phantomjs.js} +2 -20
  102. data/vendored-minitest/minitest/test.rb +7 -15
  103. metadata +32 -9
  104. data/lib/mspec/opal/main.rb.erb +0 -9
@@ -6,41 +6,41 @@ describe 'Hash' do
6
6
  end
7
7
 
8
8
  it 'stores keys directly as strings in the `keys` array' do
9
- `#@h.keys.length`.should == 2
10
- `#@h.keys[0]`.should == 'a'
11
- `#@h.keys[1]`.should == 'b'
9
+ `#@h.$$keys.length`.should == 2
10
+ `#@h.$$keys[0]`.should == 'a'
11
+ `#@h.$$keys[1]`.should == 'b'
12
12
 
13
13
  @h['c'] = 789
14
14
 
15
- `#@h.keys.length`.should == 3
16
- `#@h.keys[2]`.should == 'c'
15
+ `#@h.$$keys.length`.should == 3
16
+ `#@h.$$keys[2]`.should == 'c'
17
17
  end
18
18
 
19
19
  it 'stores values directly as objects in the `smap` object by their corresponding string key' do
20
- `Object.keys(#@h.smap).length`.should == 2
21
- `#@h.smap['a']`.should == 123
22
- `#@h.smap['b']`.should == 456
20
+ `Object.keys(#@h.$$smap).length`.should == 2
21
+ `#@h.$$smap['a']`.should == 123
22
+ `#@h.$$smap['b']`.should == 456
23
23
 
24
24
  @h['c'] = 789
25
25
 
26
- `Object.keys(#@h.smap).length`.should == 3
27
- `#@h.smap['c']`.should == 789
26
+ `Object.keys(#@h.$$smap).length`.should == 3
27
+ `#@h.$$smap['c']`.should == 789
28
28
  end
29
29
 
30
30
  it 'does not use the `map` object' do
31
- `Object.keys(#@h.map).length`.should == 0
31
+ `Object.keys(#@h.$$map).length`.should == 0
32
32
 
33
33
  @h['c'] = 789
34
34
 
35
- `Object.keys(#@h.map).length`.should == 0
35
+ `Object.keys(#@h.$$map).length`.should == 0
36
36
  end
37
37
 
38
38
  it 'uses the `map` object when an object key is added' do
39
- `Object.keys(#@h.map).length`.should == 0
39
+ `Object.keys(#@h.$$map).length`.should == 0
40
40
 
41
41
  @h[Object.new] = 789
42
42
 
43
- `Object.keys(#@h.map).length`.should == 1
43
+ `Object.keys(#@h.$$map).length`.should == 1
44
44
  end
45
45
  end
46
46
 
@@ -52,7 +52,7 @@ describe 'Hash' do
52
52
  end
53
53
 
54
54
  it 'uses a data structure called "bucket", which is a wrapper object with `key`, `key_hash`, `value`, and `next` properties' do
55
- bucket = `#@h.keys[0]`
55
+ bucket = `#@h.$$keys[0]`
56
56
  `#{bucket}.key`.should == @obj1
57
57
  `#{bucket}.key_hash`.should == @obj1.hash
58
58
  `#{bucket}.value`.should == 123
@@ -60,48 +60,48 @@ describe 'Hash' do
60
60
  end
61
61
 
62
62
  it 'stores keys in the `keys` array as "bucket" objects' do
63
- `#@h.keys.length`.should == 2
64
- `#@h.keys[0].key`.should == @obj1
65
- `#@h.keys[1].key`.should == @obj2
63
+ `#@h.$$keys.length`.should == 2
64
+ `#@h.$$keys[0].key`.should == @obj1
65
+ `#@h.$$keys[1].key`.should == @obj2
66
66
 
67
67
  obj3 = Object.new
68
68
  @h[obj3] = 789
69
69
 
70
- `#@h.keys.length`.should == 3
71
- `#@h.keys[2].key`.should == obj3
70
+ `#@h.$$keys.length`.should == 3
71
+ `#@h.$$keys[2].key`.should == obj3
72
72
  end
73
73
 
74
74
  it 'stores values in the `map` object as "bucket" objects by #hash string of their corresponding object key' do
75
- `Object.keys(#@h.map).length`.should == 2
76
- `#@h.map[#{@obj1.hash}].value`.should == 123
77
- `#@h.map[#{@obj2.hash}].value`.should == 456
75
+ `Object.keys(#@h.$$map).length`.should == 2
76
+ `#@h.$$map[#{@obj1.hash}].value`.should == 123
77
+ `#@h.$$map[#{@obj2.hash}].value`.should == 456
78
78
 
79
79
  obj3 = Object.new
80
80
  @h[obj3] = 789
81
81
 
82
- `Object.keys(#@h.map).length`.should == 3
83
- `#@h.map[#{obj3.hash}].value`.should == 789
82
+ `Object.keys(#@h.$$map).length`.should == 3
83
+ `#@h.$$map[#{obj3.hash}].value`.should == 789
84
84
  end
85
85
 
86
86
  it 'keeps a pointer to the same "bucket" object in the `keys` array and in the `map` object' do
87
- `#@h.map[#{@obj1.hash}] === #@h.keys[0]`.should == true
88
- `#@h.map[#{@obj2.hash}] === #@h.keys[1]`.should == true
87
+ `#@h.$$map[#{@obj1.hash}] === #@h.$$keys[0]`.should == true
88
+ `#@h.$$map[#{@obj2.hash}] === #@h.$$keys[1]`.should == true
89
89
  end
90
90
 
91
91
  it 'does not use the `smap` object' do
92
- `Object.keys(#@h.smap).length`.should == 0
92
+ `Object.keys(#@h.$$smap).length`.should == 0
93
93
 
94
94
  @h[Object.new] = 789
95
95
 
96
- `Object.keys(#@h.smap).length`.should == 0
96
+ `Object.keys(#@h.$$smap).length`.should == 0
97
97
  end
98
98
 
99
99
  it 'uses the `smap` object when a string key is added' do
100
- `Object.keys(#@h.smap).length`.should == 0
100
+ `Object.keys(#@h.$$smap).length`.should == 0
101
101
 
102
102
  @h['c'] = 789
103
103
 
104
- `Object.keys(#@h.smap).length`.should == 1
104
+ `Object.keys(#@h.$$smap).length`.should == 1
105
105
  end
106
106
 
107
107
  it 'allows multiple keys that #hash to the same value to be stored in the Hash' do
@@ -119,45 +119,45 @@ describe 'Hash' do
119
119
  @mock3.should_receive(:hash).at_least(1).and_return('hhh')
120
120
  @mock3.should_receive(:eql?).exactly(2).and_return(false)
121
121
 
122
- `Object.keys(#@hash.map).length`.should == 0
123
- `#@hash.keys.length`.should == 0
122
+ `Object.keys(#@hash.$$map).length`.should == 0
123
+ `#@hash.$$keys.length`.should == 0
124
124
 
125
125
  @hash[@mock1] = 123
126
- `Object.keys(#@hash.map).length`.should == 1
127
- `#@hash.keys.length`.should == 1
128
- `#@hash.keys[0] === #@hash.map['hhh']`.should == true
129
- `#@hash.keys[0].key`.should == @mock1
130
- `#@hash.keys[0].key_hash`.should == @mock1.hash
131
- `#@hash.keys[0].value`.should == 123
132
- `#@hash.keys[0].next === undefined`.should == true
126
+ `Object.keys(#@hash.$$map).length`.should == 1
127
+ `#@hash.$$keys.length`.should == 1
128
+ `#@hash.$$keys[0] === #@hash.$$map['hhh']`.should == true
129
+ `#@hash.$$keys[0].key`.should == @mock1
130
+ `#@hash.$$keys[0].key_hash`.should == @mock1.hash
131
+ `#@hash.$$keys[0].value`.should == 123
132
+ `#@hash.$$keys[0].next === undefined`.should == true
133
133
 
134
134
  @hash[@mock2] = 456
135
- `Object.keys(#@hash.map).length`.should == 1
136
- `#@hash.keys.length`.should == 2
137
- `#@hash.keys[1] === #@hash.map['hhh'].next`.should == true
138
- `#@hash.keys[1].key`.should == @mock2
139
- `#@hash.keys[1].key_hash`.should == @mock2.hash
140
- `#@hash.keys[1].value`.should == 456
141
- `#@hash.keys[1].next === undefined`.should == true
135
+ `Object.keys(#@hash.$$map).length`.should == 1
136
+ `#@hash.$$keys.length`.should == 2
137
+ `#@hash.$$keys[1] === #@hash.$$map['hhh'].next`.should == true
138
+ `#@hash.$$keys[1].key`.should == @mock2
139
+ `#@hash.$$keys[1].key_hash`.should == @mock2.hash
140
+ `#@hash.$$keys[1].value`.should == 456
141
+ `#@hash.$$keys[1].next === undefined`.should == true
142
142
 
143
143
  @hash[@mock3] = 789
144
- `Object.keys(#@hash.map).length`.should == 1
145
- `#@hash.keys.length`.should == 3
146
- `#@hash.keys[2] === #@hash.map['hhh'].next.next`.should == true
147
- `#@hash.keys[2].key`.should == @mock3
148
- `#@hash.keys[2].key_hash`.should == @mock3.hash
149
- `#@hash.keys[2].value`.should == 789
150
- `#@hash.keys[2].next === undefined`.should == true
144
+ `Object.keys(#@hash.$$map).length`.should == 1
145
+ `#@hash.$$keys.length`.should == 3
146
+ `#@hash.$$keys[2] === #@hash.$$map['hhh'].next.next`.should == true
147
+ `#@hash.$$keys[2].key`.should == @mock3
148
+ `#@hash.$$keys[2].key_hash`.should == @mock3.hash
149
+ `#@hash.$$keys[2].value`.should == 789
150
+ `#@hash.$$keys[2].next === undefined`.should == true
151
151
 
152
152
  obj = Object.new
153
153
  @hash[obj] = 999
154
- `Object.keys(#@hash.map).length`.should == 2
155
- `#@hash.keys.length`.should == 4
156
- `#@hash.keys[3] === #@hash.map[#{obj.hash}]`.should == true
157
- `#@hash.keys[3].key`.should == obj
158
- `#@hash.keys[3].key_hash`.should == obj.hash
159
- `#@hash.keys[3].value`.should == 999
160
- `#@hash.keys[3].next === undefined`.should == true
154
+ `Object.keys(#@hash.$$map).length`.should == 2
155
+ `#@hash.$$keys.length`.should == 4
156
+ `#@hash.$$keys[3] === #@hash.$$map[#{obj.hash}]`.should == true
157
+ `#@hash.$$keys[3].key`.should == obj
158
+ `#@hash.$$keys[3].key_hash`.should == obj.hash
159
+ `#@hash.$$keys[3].value`.should == 999
160
+ `#@hash.$$keys[3].next === undefined`.should == true
161
161
  end
162
162
 
163
163
  it 'correctly updates internal data structures when deleting keys' do
@@ -188,145 +188,145 @@ describe 'Hash' do
188
188
  @obj1 => 'xyz'
189
189
  }
190
190
 
191
- `#@hash.map.hasOwnProperty('hhh')`.should == true
192
- `#@hash.map.hasOwnProperty(#{@obj1.hash})`.should == true
193
- `#@hash.smap.hasOwnProperty('a')`.should == true
194
- `#@hash.smap.hasOwnProperty('b')`.should == true
195
- `#@hash.smap.hasOwnProperty('c')`.should == true
196
-
197
- `#@hash.keys.length`.should == 8
198
- `Object.keys(#@hash.map).length`.should == 2
199
- `Object.keys(#@hash.smap).length`.should == 3
200
-
201
- `#@hash.keys[0].key`.should == @mock1
202
- `#@hash.keys[1]`.should == 'a'
203
- `#@hash.keys[2].key`.should == @mock2
204
- `#@hash.keys[3]`.should == 'b'
205
- `#@hash.keys[4].key`.should == @mock3
206
- `#@hash.keys[5].key`.should == @mock4
207
- `#@hash.keys[6]`.should == 'c'
208
- `#@hash.keys[7].key`.should == @obj1
209
-
210
- `#@hash.map['hhh'] === #@hash.keys[0]`.should == true
211
- `#@hash.keys[0].next === #@hash.keys[2]`.should == true
212
- `#@hash.keys[2].next === #@hash.keys[4]`.should == true
213
- `#@hash.keys[4].next === #@hash.keys[5]`.should == true
214
- `#@hash.keys[5].next === undefined`.should == true
191
+ `#@hash.$$map.hasOwnProperty('hhh')`.should == true
192
+ `#@hash.$$map.hasOwnProperty(#{@obj1.hash})`.should == true
193
+ `#@hash.$$smap.hasOwnProperty('a')`.should == true
194
+ `#@hash.$$smap.hasOwnProperty('b')`.should == true
195
+ `#@hash.$$smap.hasOwnProperty('c')`.should == true
196
+
197
+ `#@hash.$$keys.length`.should == 8
198
+ `Object.keys(#@hash.$$map).length`.should == 2
199
+ `Object.keys(#@hash.$$smap).length`.should == 3
200
+
201
+ `#@hash.$$keys[0].key`.should == @mock1
202
+ `#@hash.$$keys[1]`.should == 'a'
203
+ `#@hash.$$keys[2].key`.should == @mock2
204
+ `#@hash.$$keys[3]`.should == 'b'
205
+ `#@hash.$$keys[4].key`.should == @mock3
206
+ `#@hash.$$keys[5].key`.should == @mock4
207
+ `#@hash.$$keys[6]`.should == 'c'
208
+ `#@hash.$$keys[7].key`.should == @obj1
209
+
210
+ `#@hash.$$map['hhh'] === #@hash.$$keys[0]`.should == true
211
+ `#@hash.$$keys[0].next === #@hash.$$keys[2]`.should == true
212
+ `#@hash.$$keys[2].next === #@hash.$$keys[4]`.should == true
213
+ `#@hash.$$keys[4].next === #@hash.$$keys[5]`.should == true
214
+ `#@hash.$$keys[5].next === undefined`.should == true
215
215
 
216
216
  @hash.delete @mock2
217
217
 
218
- `#@hash.keys.length`.should == 7
219
- `Object.keys(#@hash.map).length`.should == 2
220
- `Object.keys(#@hash.smap).length`.should == 3
218
+ `#@hash.$$keys.length`.should == 7
219
+ `Object.keys(#@hash.$$map).length`.should == 2
220
+ `Object.keys(#@hash.$$smap).length`.should == 3
221
221
 
222
- `#@hash.keys[0].key`.should == @mock1
223
- `#@hash.keys[1]`.should == 'a'
224
- `#@hash.keys[2]`.should == 'b'
225
- `#@hash.keys[3].key`.should == @mock3
226
- `#@hash.keys[4].key`.should == @mock4
227
- `#@hash.keys[5]`.should == 'c'
228
- `#@hash.keys[6].key`.should == @obj1
222
+ `#@hash.$$keys[0].key`.should == @mock1
223
+ `#@hash.$$keys[1]`.should == 'a'
224
+ `#@hash.$$keys[2]`.should == 'b'
225
+ `#@hash.$$keys[3].key`.should == @mock3
226
+ `#@hash.$$keys[4].key`.should == @mock4
227
+ `#@hash.$$keys[5]`.should == 'c'
228
+ `#@hash.$$keys[6].key`.should == @obj1
229
229
 
230
- `#@hash.map['hhh'] === #@hash.keys[0]`.should == true
231
- `#@hash.keys[0].next === #@hash.keys[3]`.should == true
232
- `#@hash.keys[3].next === #@hash.keys[4]`.should == true
233
- `#@hash.keys[4].next === undefined`.should == true
230
+ `#@hash.$$map['hhh'] === #@hash.$$keys[0]`.should == true
231
+ `#@hash.$$keys[0].next === #@hash.$$keys[3]`.should == true
232
+ `#@hash.$$keys[3].next === #@hash.$$keys[4]`.should == true
233
+ `#@hash.$$keys[4].next === undefined`.should == true
234
234
 
235
235
  @hash.delete @mock4
236
236
 
237
- `#@hash.keys.length`.should == 6
238
- `Object.keys(#@hash.map).length`.should == 2
239
- `Object.keys(#@hash.smap).length`.should == 3
237
+ `#@hash.$$keys.length`.should == 6
238
+ `Object.keys(#@hash.$$map).length`.should == 2
239
+ `Object.keys(#@hash.$$smap).length`.should == 3
240
240
 
241
- `#@hash.keys[0].key`.should == @mock1
242
- `#@hash.keys[1]`.should == 'a'
243
- `#@hash.keys[2]`.should == 'b'
244
- `#@hash.keys[3].key`.should == @mock3
245
- `#@hash.keys[4]`.should == 'c'
246
- `#@hash.keys[5].key`.should == @obj1
241
+ `#@hash.$$keys[0].key`.should == @mock1
242
+ `#@hash.$$keys[1]`.should == 'a'
243
+ `#@hash.$$keys[2]`.should == 'b'
244
+ `#@hash.$$keys[3].key`.should == @mock3
245
+ `#@hash.$$keys[4]`.should == 'c'
246
+ `#@hash.$$keys[5].key`.should == @obj1
247
247
 
248
- `#@hash.map['hhh'] === #@hash.keys[0]`.should == true
249
- `#@hash.keys[0].next === #@hash.keys[3]`.should == true
250
- `#@hash.keys[3].next === undefined`.should == true
248
+ `#@hash.$$map['hhh'] === #@hash.$$keys[0]`.should == true
249
+ `#@hash.$$keys[0].next === #@hash.$$keys[3]`.should == true
250
+ `#@hash.$$keys[3].next === undefined`.should == true
251
251
 
252
252
  @hash.delete @mock1
253
253
 
254
- `#@hash.keys.length`.should == 5
255
- `Object.keys(#@hash.map).length`.should == 2
256
- `Object.keys(#@hash.smap).length`.should == 3
254
+ `#@hash.$$keys.length`.should == 5
255
+ `Object.keys(#@hash.$$map).length`.should == 2
256
+ `Object.keys(#@hash.$$smap).length`.should == 3
257
257
 
258
- `#@hash.keys[0]`.should == 'a'
259
- `#@hash.keys[1]`.should == 'b'
260
- `#@hash.keys[2].key`.should == @mock3
261
- `#@hash.keys[3]`.should == 'c'
262
- `#@hash.keys[4].key`.should == @obj1
258
+ `#@hash.$$keys[0]`.should == 'a'
259
+ `#@hash.$$keys[1]`.should == 'b'
260
+ `#@hash.$$keys[2].key`.should == @mock3
261
+ `#@hash.$$keys[3]`.should == 'c'
262
+ `#@hash.$$keys[4].key`.should == @obj1
263
263
 
264
- `#@hash.map['hhh'] === #@hash.keys[2]`.should == true
265
- `#@hash.keys[2].next === undefined`.should == true
264
+ `#@hash.$$map['hhh'] === #@hash.$$keys[2]`.should == true
265
+ `#@hash.$$keys[2].next === undefined`.should == true
266
266
 
267
267
  @hash.delete @mock3
268
268
 
269
- `#@hash.keys.length`.should == 4
270
- `Object.keys(#@hash.map).length`.should == 1
271
- `Object.keys(#@hash.smap).length`.should == 3
269
+ `#@hash.$$keys.length`.should == 4
270
+ `Object.keys(#@hash.$$map).length`.should == 1
271
+ `Object.keys(#@hash.$$smap).length`.should == 3
272
272
 
273
- `#@hash.keys[0]`.should == 'a'
274
- `#@hash.keys[1]`.should == 'b'
275
- `#@hash.keys[2]`.should == 'c'
276
- `#@hash.keys[3].key`.should == @obj1
273
+ `#@hash.$$keys[0]`.should == 'a'
274
+ `#@hash.$$keys[1]`.should == 'b'
275
+ `#@hash.$$keys[2]`.should == 'c'
276
+ `#@hash.$$keys[3].key`.should == @obj1
277
277
 
278
- `#@hash.map['hhh'] === undefined`.should == true
278
+ `#@hash.$$map['hhh'] === undefined`.should == true
279
279
 
280
280
  @hash.delete @obj1
281
281
 
282
- `#@hash.keys.length`.should == 3
283
- `Object.keys(#@hash.map).length`.should == 0
284
- `Object.keys(#@hash.smap).length`.should == 3
282
+ `#@hash.$$keys.length`.should == 3
283
+ `Object.keys(#@hash.$$map).length`.should == 0
284
+ `Object.keys(#@hash.$$smap).length`.should == 3
285
285
 
286
- `#@hash.keys[0]`.should == 'a'
287
- `#@hash.keys[1]`.should == 'b'
288
- `#@hash.keys[2]`.should == 'c'
286
+ `#@hash.$$keys[0]`.should == 'a'
287
+ `#@hash.$$keys[1]`.should == 'b'
288
+ `#@hash.$$keys[2]`.should == 'c'
289
289
 
290
- `#@hash.map[#{@obj1.hash}] === undefined`.should == true
290
+ `#@hash.$$map[#{@obj1.hash}] === undefined`.should == true
291
291
 
292
292
  @hash.delete 'b'
293
293
 
294
- `#@hash.keys.length`.should == 2
295
- `Object.keys(#@hash.map).length`.should == 0
296
- `Object.keys(#@hash.smap).length`.should == 2
294
+ `#@hash.$$keys.length`.should == 2
295
+ `Object.keys(#@hash.$$map).length`.should == 0
296
+ `Object.keys(#@hash.$$smap).length`.should == 2
297
297
 
298
- `#@hash.keys[0]`.should == 'a'
299
- `#@hash.keys[1]`.should == 'c'
300
- `#@hash.smap['a']`.should == 'abc'
301
- `#@hash.smap['b'] === undefined`.should == true
302
- `#@hash.smap['c']`.should == 'ghi'
298
+ `#@hash.$$keys[0]`.should == 'a'
299
+ `#@hash.$$keys[1]`.should == 'c'
300
+ `#@hash.$$smap['a']`.should == 'abc'
301
+ `#@hash.$$smap['b'] === undefined`.should == true
302
+ `#@hash.$$smap['c']`.should == 'ghi'
303
303
 
304
304
  @hash.delete 'c'
305
305
 
306
- `#@hash.keys.length`.should == 1
307
- `Object.keys(#@hash.map).length`.should == 0
308
- `Object.keys(#@hash.smap).length`.should == 1
306
+ `#@hash.$$keys.length`.should == 1
307
+ `Object.keys(#@hash.$$map).length`.should == 0
308
+ `Object.keys(#@hash.$$smap).length`.should == 1
309
309
 
310
- `#@hash.keys[0]`.should == 'a'
311
- `#@hash.smap['a']`.should == 'abc'
312
- `#@hash.smap['b'] === undefined`.should == true
313
- `#@hash.smap['c'] === undefined`.should == true
310
+ `#@hash.$$keys[0]`.should == 'a'
311
+ `#@hash.$$smap['a']`.should == 'abc'
312
+ `#@hash.$$smap['b'] === undefined`.should == true
313
+ `#@hash.$$smap['c'] === undefined`.should == true
314
314
 
315
315
  @hash.delete 'a'
316
316
 
317
- `#@hash.keys.length`.should == 0
318
- `Object.keys(#@hash.map).length`.should == 0
319
- `Object.keys(#@hash.smap).length`.should == 0
317
+ `#@hash.$$keys.length`.should == 0
318
+ `Object.keys(#@hash.$$map).length`.should == 0
319
+ `Object.keys(#@hash.$$smap).length`.should == 0
320
320
 
321
- `#@hash.smap['a'] === undefined`.should == true
322
- `#@hash.smap['b'] === undefined`.should == true
323
- `#@hash.smap['c'] === undefined`.should == true
321
+ `#@hash.$$smap['a'] === undefined`.should == true
322
+ `#@hash.$$smap['b'] === undefined`.should == true
323
+ `#@hash.$$smap['c'] === undefined`.should == true
324
324
 
325
- `#@hash.map.hasOwnProperty('hhh')`.should == false
326
- `#@hash.map.hasOwnProperty(#{@obj1.hash})`.should == false
327
- `#@hash.smap.hasOwnProperty('a')`.should == false
328
- `#@hash.smap.hasOwnProperty('b')`.should == false
329
- `#@hash.smap.hasOwnProperty('c')`.should == false
325
+ `#@hash.$$map.hasOwnProperty('hhh')`.should == false
326
+ `#@hash.$$map.hasOwnProperty(#{@obj1.hash})`.should == false
327
+ `#@hash.$$smap.hasOwnProperty('a')`.should == false
328
+ `#@hash.$$smap.hasOwnProperty('b')`.should == false
329
+ `#@hash.$$smap.hasOwnProperty('c')`.should == false
330
330
  end
331
331
  end
332
332
  end
@@ -0,0 +1,70 @@
1
+ module KernelExit
2
+ extend self
3
+ attr_accessor :status, :original_proc, :proc, :out
4
+
5
+ self.original_proc = `Opal.exit`
6
+ self.proc = `function(status){ #{KernelExit.status = `status`} }`
7
+
8
+ def out_after_exit
9
+ `Opal.exit = #{proc}`
10
+ exit
11
+ out
12
+ ensure
13
+ `Opal.exit = #{original_proc}`
14
+ end
15
+
16
+ def reset!
17
+ self.out = []
18
+ end
19
+ end
20
+
21
+ describe "Kernel.at_exit" do
22
+ before { KernelExit.reset! }
23
+
24
+ def print(n)
25
+ KernelExit.out << n
26
+ end
27
+
28
+ it "runs after all other code" do
29
+ Kernel.at_exit {print 5}
30
+ print 6
31
+
32
+ KernelExit.out_after_exit.should == [6,5]
33
+ end
34
+
35
+ it "runs in reverse order of registration" do
36
+ at_exit {print 4}
37
+ at_exit {print 5}
38
+ print 6
39
+ at_exit {print 7}
40
+
41
+ KernelExit.out_after_exit.should == [6,7,5,4]
42
+ end
43
+
44
+ it "allows calling exit inside at_exit handler" do
45
+ at_exit {print 3}
46
+ at_exit {
47
+ print 4
48
+ exit
49
+ # print 5 # This one is added to out because Opal.exit doesn't actually exit
50
+ }
51
+ at_exit {print 6}
52
+
53
+ KernelExit.out_after_exit.should == [6,4,3]
54
+ end
55
+
56
+ # INCOMPLETE: the spec implementation is tricky here
57
+ # it "gives access to the last raised exception" do
58
+ # begin
59
+ # at_exit do
60
+ # print $!.message
61
+ # end
62
+ # raise 'foo' rescue nil
63
+ # p [:err, $!]
64
+ # rescue
65
+ # end
66
+ #
67
+ # KernelExit.out_after_exit.should == ['foo']
68
+ # end
69
+
70
+ end