opal 0.9.0.beta2 → 0.9.0.rc1

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.
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