opal 0.3.27 → 0.3.28

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 (148) hide show
  1. data/.gitignore +2 -1
  2. data/CONTRIBUTING.md +24 -0
  3. data/README.md +6 -5
  4. data/Rakefile +12 -2
  5. data/core/array.rb +3 -31
  6. data/core/enumerable.rb +32 -4
  7. data/core/hash.rb +218 -186
  8. data/core/json.rb +3 -2
  9. data/core/kernel.rb +28 -28
  10. data/core/numeric.rb +2 -2
  11. data/core/runtime.js +0 -1
  12. data/lib/opal.rb +4 -2
  13. data/lib/opal/grammar.rb +6 -2
  14. data/lib/opal/grammar.y +3 -0
  15. data/lib/opal/lexer.rb +25 -10
  16. data/lib/opal/parser.rb +75 -34
  17. data/lib/opal/scope.rb +7 -7
  18. data/lib/opal/version.rb +1 -1
  19. data/opal.gemspec +1 -1
  20. data/spec/core/array/reduce_spec.rb +31 -0
  21. data/spec/{opal → core}/array/to_json_spec.rb +0 -0
  22. data/spec/core/boolean/and_spec.rb +17 -0
  23. data/spec/core/boolean/inspect_spec.rb +9 -0
  24. data/spec/core/boolean/or_spec.rb +17 -0
  25. data/spec/{opal → core}/boolean/singleton_class_spec.rb +0 -0
  26. data/spec/{opal → core}/boolean/to_json_spec.rb +1 -1
  27. data/spec/core/boolean/to_s_spec.rb +9 -0
  28. data/spec/core/boolean/xor_spec.rb +17 -0
  29. data/spec/{opal → core}/class/bridge_class_spec.rb +0 -0
  30. data/spec/{opal → core}/class/instance_methods_spec.rb +0 -0
  31. data/spec/core/class/last_value_spec.rb +68 -0
  32. data/spec/core/enumerable/detect_spec.rb +1 -1
  33. data/spec/core/enumerable/find_spec.rb +1 -1
  34. data/spec/{opal → core}/hash/to_json_spec.rb +0 -0
  35. data/spec/{opal → core}/hash/to_native_spec.rb +0 -0
  36. data/spec/{opal → core}/json/parse_spec.rb +0 -0
  37. data/spec/core/kernel/block_given.rb +30 -0
  38. data/spec/core/kernel/methods_spec.rb +11 -0
  39. data/spec/core/kernel/p_spec.rb +13 -0
  40. data/spec/{opal → core}/kernel/to_json_spec.rb +0 -0
  41. data/spec/{opal → core}/nil/to_json_spec.rb +0 -0
  42. data/spec/core/numeric/abs_spec.rb +12 -0
  43. data/spec/core/numeric/bit_and_spec.rb +7 -0
  44. data/spec/core/numeric/bit_or_spec.rb +8 -0
  45. data/spec/core/numeric/bit_xor_spec.rb +6 -0
  46. data/spec/core/numeric/ceil_spec.rb +8 -0
  47. data/spec/core/numeric/chr_spec.rb +8 -0
  48. data/spec/core/numeric/comparison_spec.rb +24 -0
  49. data/spec/core/numeric/complement_spec.rb +8 -0
  50. data/spec/core/numeric/divide_spec.rb +10 -0
  51. data/spec/core/numeric/downto_spec.rb +19 -0
  52. data/spec/core/numeric/eql_spec.rb +9 -0
  53. data/spec/core/numeric/even_spec.rb +21 -0
  54. data/spec/core/numeric/exponent_spec.rb +33 -0
  55. data/spec/core/numeric/floor_spec.rb +8 -0
  56. data/spec/core/numeric/gt_spec.rb +11 -0
  57. data/spec/core/numeric/gte_spec.rb +12 -0
  58. data/spec/core/numeric/integer_spec.rb +9 -0
  59. data/spec/core/numeric/left_shift_spec.rb +21 -0
  60. data/spec/core/numeric/lt_spec.rb +11 -0
  61. data/spec/core/numeric/lte_spec.rb +12 -0
  62. data/spec/core/numeric/magnitude_spec.rb +12 -0
  63. data/spec/core/numeric/minus_spec.rb +8 -0
  64. data/spec/core/numeric/modulo_spec.rb +19 -0
  65. data/spec/core/numeric/multiply_spec.rb +9 -0
  66. data/spec/core/numeric/next_spec.rb +9 -0
  67. data/spec/core/numeric/odd_spec.rb +21 -0
  68. data/spec/core/numeric/ord_spec.rb +9 -0
  69. data/spec/core/numeric/plus_spec.rb +8 -0
  70. data/spec/core/numeric/pred_spec.rb +7 -0
  71. data/spec/core/numeric/right_shift_spec.rb +25 -0
  72. data/spec/core/numeric/succ_spec.rb +9 -0
  73. data/spec/core/numeric/times_spec.rb +36 -0
  74. data/spec/core/numeric/to_f_spec.rb +7 -0
  75. data/spec/core/numeric/to_i_spec.rb +7 -0
  76. data/spec/{opal → core}/numeric/to_json_spec.rb +0 -0
  77. data/spec/core/numeric/to_s_spec.rb +8 -0
  78. data/spec/core/numeric/uminus_spec.rb +9 -0
  79. data/spec/core/numeric/upto_spec.rb +19 -0
  80. data/spec/core/numeric/zero_spec.rb +7 -0
  81. data/spec/{opal → core}/runtime/call_spec.rb +0 -0
  82. data/spec/{opal → core}/runtime/class_hierarchy_spec.rb +0 -0
  83. data/spec/{opal → core}/runtime/def_spec.rb +0 -0
  84. data/spec/{opal → core}/runtime/defined_spec.rb +0 -0
  85. data/spec/{opal → core}/runtime/super_spec.rb +0 -0
  86. data/spec/{opal → core}/string/demodulize_spec.rb +0 -0
  87. data/spec/{opal → core}/string/to_json_spec.rb +0 -0
  88. data/spec/{opal → core}/string/underscore_spec.rb +0 -0
  89. data/spec/{opal → core}/strscan/check_spec.rb +0 -0
  90. data/spec/{opal → core}/strscan/scan_spec.rb +0 -0
  91. data/spec/{lib/grammar → grammar}/alias_spec.rb +0 -0
  92. data/spec/{lib/grammar → grammar}/and_spec.rb +0 -0
  93. data/spec/{lib/grammar → grammar}/array_spec.rb +0 -0
  94. data/spec/{lib/grammar → grammar}/attrasgn_spec.rb +0 -0
  95. data/spec/{lib/grammar → grammar}/begin_spec.rb +0 -0
  96. data/spec/{lib/grammar → grammar}/block_spec.rb +0 -0
  97. data/spec/{lib/grammar → grammar}/break_spec.rb +0 -0
  98. data/spec/{lib/grammar → grammar}/call_spec.rb +23 -1
  99. data/spec/{lib/grammar → grammar}/class_spec.rb +0 -0
  100. data/spec/{lib/grammar → grammar}/const_spec.rb +0 -0
  101. data/spec/{lib/grammar → grammar}/cvar_spec.rb +0 -0
  102. data/spec/{lib/grammar → grammar}/def_spec.rb +0 -0
  103. data/spec/{lib/grammar → grammar}/false_spec.rb +0 -0
  104. data/spec/{lib/grammar → grammar}/file_spec.rb +0 -0
  105. data/spec/{lib/grammar → grammar}/gvar_spec.rb +0 -0
  106. data/spec/{lib/grammar → grammar}/hash_spec.rb +0 -0
  107. data/spec/{lib/grammar → grammar}/iasgn_spec.rb +0 -0
  108. data/spec/{lib/grammar → grammar}/if_spec.rb +0 -0
  109. data/spec/{lib/grammar → grammar}/iter_spec.rb +0 -0
  110. data/spec/{lib/grammar → grammar}/ivar_spec.rb +0 -0
  111. data/spec/{lib/grammar → grammar}/lambda_spec.rb +0 -0
  112. data/spec/{lib/grammar → grammar}/lasgn_spec.rb +0 -0
  113. data/spec/{lib/grammar → grammar}/line_spec.rb +0 -0
  114. data/spec/{lib/grammar → grammar}/lvar_spec.rb +0 -0
  115. data/spec/{lib/grammar → grammar}/masgn_spec.rb +0 -0
  116. data/spec/{lib/grammar → grammar}/module_spec.rb +0 -0
  117. data/spec/{lib/grammar → grammar}/nil_spec.rb +0 -0
  118. data/spec/{lib/grammar → grammar}/not_spec.rb +0 -0
  119. data/spec/{lib/grammar → grammar}/op_asgn1_spec.rb +0 -0
  120. data/spec/{lib/grammar → grammar}/op_asgn2_spec.rb +0 -0
  121. data/spec/{lib/grammar → grammar}/or_spec.rb +0 -0
  122. data/spec/{lib/grammar → grammar}/return_spec.rb +0 -0
  123. data/spec/{lib/grammar → grammar}/sclass_spec.rb +0 -0
  124. data/spec/{lib/grammar → grammar}/self_spec.rb +0 -0
  125. data/spec/{lib/grammar → grammar}/str_spec.rb +7 -0
  126. data/spec/{lib/grammar → grammar}/super_spec.rb +0 -0
  127. data/spec/{lib/grammar → grammar}/true_spec.rb +0 -0
  128. data/spec/{lib/grammar → grammar}/undef_spec.rb +0 -0
  129. data/spec/{lib/grammar → grammar}/unless_spec.rb +0 -0
  130. data/spec/{lib/grammar → grammar}/while_spec.rb +0 -0
  131. data/spec/{lib/grammar → grammar}/xstr_spec.rb +0 -0
  132. data/spec/{lib/grammar → grammar}/yield_spec.rb +0 -0
  133. data/spec/language/string_spec.rb +5 -0
  134. data/spec/{lib/parser → parser}/simple_spec.rb +0 -0
  135. metadata +231 -159
  136. data/spec/core/false/and_spec.rb +0 -9
  137. data/spec/core/false/inspect_spec.rb +0 -5
  138. data/spec/core/false/or_spec.rb +0 -9
  139. data/spec/core/false/to_s_spec.rb +0 -5
  140. data/spec/core/false/xor_spec.rb +0 -9
  141. data/spec/core/true/and_spec.rb +0 -9
  142. data/spec/core/true/inspect_spec.rb +0 -5
  143. data/spec/core/true/or_spec.rb +0 -9
  144. data/spec/core/true/to_s_spec.rb +0 -5
  145. data/spec/core/true/xor_spec.rb +0 -9
  146. data/spec/lib/erb_parser/simple.erb +0 -1
  147. data/spec/opal/kernel/attribute_spec.rb +0 -57
  148. data/spec/opal/runtime/method_missing_spec.rb +0 -17
data/.gitignore CHANGED
@@ -3,4 +3,5 @@
3
3
  .yardoc
4
4
  .bundle
5
5
  Gemfile.lock
6
- build
6
+ build
7
+ gh-pages
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,24 @@
1
+ # Contributing
2
+
3
+ ## Quick Start
4
+
5
+ Clone repo:
6
+
7
+ ```
8
+ $ git clone git://github.com/opal/opal.git
9
+ ```
10
+
11
+ Get dependencies:
12
+
13
+ ```
14
+ $ bundle
15
+ ```
16
+
17
+ ## Tests
18
+
19
+ You need phantomjs installed to run tests. To build opal, its dependencies
20
+ and all specs, run:
21
+
22
+ ```
23
+ $ rake
24
+ ```
data/README.md CHANGED
@@ -6,21 +6,22 @@ Opal is a ruby to javascript source-to-source compiler. It also has an
6
6
  implementation of the ruby corelib.
7
7
 
8
8
  Opal is [hosted on github](http://github.com/opal/opal), and there
9
- is a Freenode IRC channel at `#opal`. There is also a [google group for opal](http://groups.google.com/forum/#!forum/opalrb).
9
+ is a Freenode IRC channel at [#opal](http://webchat.freenode.net/?channels=opal). There is also a [google group for opal](http://groups.google.com/forum/#!forum/opalrb).
10
10
 
11
11
  ## Usage
12
12
 
13
- See the website, [http://opal.github.com](http://opal.github.com).
13
+ See the website, [http://opalrb.org](http://opalrb.org).
14
14
 
15
15
  ## Running tests
16
16
 
17
- Build the runtime, tests and dependencies, and then run the tests all in one
18
- go:
17
+ Build the runtime, tests and dependencies, and run the tests with:
19
18
 
20
19
  ```
21
- $ rake
20
+ rake
22
21
  ```
23
22
 
23
+ You can just build opal using `rake opal`.
24
+
24
25
  Alternatively, after building, you can open `spec/index.html` in any
25
26
  web browser.
26
27
 
data/Rakefile CHANGED
@@ -10,6 +10,16 @@ end
10
10
  # build runtime, dependencies and specs, then run the tests
11
11
  task :default => %w[opal opal:test]
12
12
 
13
+ desc "opal.min.js and opal-parser.min.js"
14
+ task :min do
15
+ %w[opal opal-parser].each do |file|
16
+ puts " * #{file}.min.js"
17
+ File.open("build/#{file}.min.js", "w+") do |o|
18
+ o.puts uglify(File.read "build/#{file}.js")
19
+ end
20
+ end
21
+ end
22
+
13
23
  desc "Check file sizes for opal.js runtime"
14
24
  task :sizes do
15
25
  o = File.read 'build/opal.js'
@@ -44,11 +54,11 @@ def gzip(str)
44
54
  end
45
55
 
46
56
  # For testing just specific sections of opal
47
- desc "Build each test case"
57
+ desc "Build each test case into build/"
48
58
  task :test_cases do
49
59
  FileUtils.mkdir_p 'build/test_cases'
50
60
 
51
- sources = Dir['spec/core/*', 'spec/language', 'spec/lib', 'spec/opal']
61
+ sources = Dir['spec/core/*', 'spec/language', 'spec/parser', 'spec/grammar']
52
62
 
53
63
  sources.each do |c|
54
64
  dest = "build/test_cases/#{File.basename c}"
data/core/array.rb CHANGED
@@ -666,21 +666,8 @@ class Array < `Array`
666
666
  def reject!(&block)
667
667
  %x{
668
668
  var original = #{self}.length;
669
-
670
- for (var i = 0, length = #{self}.length, value; i < length; i++) {
671
- if ((value = block.call(__context, #{self}[i])) === __breaker) {
672
- return __breaker.$v;
673
- }
674
-
675
- if (value !== false && value !== nil) {
676
- #{self}.splice(i, 1);
677
-
678
- length--;
679
- i--;
680
- }
681
- }
682
-
683
- return original === #{self}.length ? nil : #{self};
669
+ #{ delete_if &block };
670
+ return #{self}.length === original ? nil : #{self};
684
671
  }
685
672
  end
686
673
 
@@ -756,22 +743,7 @@ class Array < `Array`
756
743
  def select!(&block)
757
744
  %x{
758
745
  var original = #{self}.length;
759
-
760
- for (var i = 0, length = original, item, value; i < length; i++) {
761
- item = #{self}[i];
762
-
763
- if ((value = block(__context, item)) === __breaker) {
764
- return __breaker.$v;
765
- }
766
-
767
- if (value === false || value === nil) {
768
- #{self}.splice(i, 1);
769
-
770
- length--;
771
- i--;
772
- }
773
- }
774
-
746
+ #{ keep_if &block };
775
747
  return #{self}.length === original ? nil : #{self};
776
748
  }
777
749
  end
data/core/enumerable.rb CHANGED
@@ -96,6 +96,30 @@ module Enumerable
96
96
  }
97
97
  end
98
98
 
99
+ def reduce(object, &block)
100
+ %x{
101
+ var result = #{object} == undefined ? 0 : #{object};
102
+
103
+ var proc = function() {
104
+ var obj = __slice.call(arguments), value;
105
+
106
+ if ((value = block.apply(__context, [result].concat(obj))) === __breaker) {
107
+ result = __breaker.$v;
108
+ __breaker.$v = nil;
109
+
110
+ return __breaker;
111
+ }
112
+
113
+ result = value;
114
+ };
115
+
116
+ #{self}.$each._p = proc;
117
+ #{self}.$each();
118
+
119
+ return result;
120
+ }
121
+ end
122
+
99
123
  def count(object, &block)
100
124
  %x{
101
125
  var result = 0;
@@ -193,8 +217,8 @@ module Enumerable
193
217
  result.push(obj);
194
218
  return value;
195
219
  }
196
-
197
-
220
+
221
+
198
222
  return __breaker;
199
223
  };
200
224
 
@@ -283,7 +307,7 @@ module Enumerable
283
307
  var proc, result = nil, index = 0;
284
308
 
285
309
  if (object != null) {
286
- proc = function (obj) {
310
+ proc = function (obj) {
287
311
  if (#{ `obj` == `object` }) {
288
312
  result = index;
289
313
  return __breaker;
@@ -376,9 +400,13 @@ module Enumerable
376
400
  }
377
401
  end
378
402
 
403
+ alias map collect
404
+
379
405
  alias select find_all
380
406
 
381
407
  alias take first
382
408
 
383
409
  alias to_a entries
384
- end
410
+
411
+ alias inject reduce
412
+ end
data/core/hash.rb CHANGED
@@ -5,17 +5,35 @@ class Hash
5
5
  __hash = Opal.hash = function() {
6
6
  var hash = new Hash,
7
7
  args = __slice.call(arguments),
8
+ keys = [],
8
9
  assocs = {};
9
10
 
10
11
  hash.map = assocs;
12
+ hash.keys = keys;
11
13
 
12
14
  for (var i = 0, length = args.length, key; i < length; i++) {
13
- key = args[i];
14
- assocs[key] = [key, args[++i]];
15
+ var key = args[i], obj = args[++i];
16
+
17
+ if (assocs[key] == null) {
18
+ keys.push(key);
19
+ }
20
+
21
+ assocs[key] = obj;
15
22
  }
16
23
 
17
24
  return hash;
18
25
  };
26
+
27
+ // hash2 is a faster creator for hashes that just use symbols and
28
+ // strings as keys. The map and keys array can be constructed at
29
+ // compile time, so they are just added here by the constructor
30
+ // function
31
+ __hash2 = Opal.hash2 = function(keys, map) {
32
+ var hash = new Hash;
33
+ hash.keys = keys;
34
+ hash.map = map;
35
+ return hash;
36
+ }
19
37
  }
20
38
 
21
39
  def self.[](*objs)
@@ -28,10 +46,11 @@ class Hash
28
46
 
29
47
  def self.from_native(obj)
30
48
  %x{
31
- var hash = __hash(), map = hash.map;
49
+ var hash = __hash(), map = hash.map, keys = hash.keys;
32
50
 
33
51
  for (var key in obj) {
34
- map[key] = [key, obj[key]]
52
+ keys.push(key);
53
+ map[key] = obj[key];
35
54
  }
36
55
 
37
56
  return hash;
@@ -59,20 +78,19 @@ class Hash
59
78
  return true;
60
79
  }
61
80
 
62
- if (!other.map) {
81
+ if (!other.map || !other.keys) {
82
+ return false;
83
+ }
84
+
85
+ if (#{self}.keys.length !== other.keys.length) {
63
86
  return false;
64
87
  }
65
88
 
66
89
  var map = #{self}.map,
67
90
  map2 = other.map;
68
91
 
69
- for (var assoc in map) {
70
- if (!map2[assoc]) {
71
- return false;
72
- }
73
-
74
- var obj = map[assoc][1],
75
- obj2 = map2[assoc][1];
92
+ for (var i = 0, length = #{self}.keys.length; i < length; i++) {
93
+ var key = #{self}.keys[i], obj = map[key], obj2 = map2[key];
76
94
 
77
95
  if (#{`obj` != `obj2`}) {
78
96
  return false;
@@ -85,10 +103,10 @@ class Hash
85
103
 
86
104
  def [](key)
87
105
  %x{
88
- var bucket;
106
+ var bucket = #{self}.map[key];
89
107
 
90
- if (bucket = #{self}.map[key]) {
91
- return bucket[1];
108
+ if (bucket != null) {
109
+ return bucket;
92
110
  }
93
111
 
94
112
  var proc = #{@proc};
@@ -103,7 +121,13 @@ class Hash
103
121
 
104
122
  def []=(key, value)
105
123
  %x{
106
- #{self}.map[key] = [key, value];
124
+ var map = #{self}.map;
125
+
126
+ if (!__hasOwn.call(map, key)) {
127
+ #{self}.keys.push(key);
128
+ }
129
+
130
+ map[key] = value;
107
131
 
108
132
  return value;
109
133
  }
@@ -111,11 +135,13 @@ class Hash
111
135
 
112
136
  def assoc(object)
113
137
  %x{
114
- for (var assoc in #{self}.map) {
115
- var bucket = #{self}.map[assoc];
138
+ var keys = #{self}.keys, key;
139
+
140
+ for (var i = 0, length = keys.length; i < length; i++) {
141
+ key = keys[i];
116
142
 
117
- if (#{`bucket[0]` == `object`}) {
118
- return [bucket[0], bucket[1]];
143
+ if (#{`key` == object}) {
144
+ return [key, #{self}.map[key]];
119
145
  }
120
146
  }
121
147
 
@@ -126,7 +152,7 @@ class Hash
126
152
  def clear
127
153
  %x{
128
154
  #{self}.map = {};
129
-
155
+ #{self}.keys = [];
130
156
  return #{self};
131
157
  }
132
158
  end
@@ -135,10 +161,12 @@ class Hash
135
161
  %x{
136
162
  var result = __hash(),
137
163
  map = #{self}.map,
138
- map2 = result.map;
164
+ map2 = result.map,
165
+ keys2 = result.keys;
139
166
 
140
- for (var assoc in map) {
141
- map2[assoc] = [map[assoc][0], map[assoc][1]];
167
+ for (var i = 0, length = #{self}.keys.length; i < length; i++) {
168
+ keys2.push(#{self}.keys[i]);
169
+ map2[#{self}.keys[i]] = map[#{self}.keys[i]];
142
170
  }
143
171
 
144
172
  return result;
@@ -163,12 +191,12 @@ class Hash
163
191
 
164
192
  def delete(key)
165
193
  %x{
166
- var map = #{self}.map, result;
167
-
168
- if (result = map[key]) {
169
- result = result[1];
194
+ var map = #{self}.map, result = map[key];
170
195
 
196
+ if (result != null) {
171
197
  delete map[key];
198
+ #{self}.keys.$delete(key);
199
+
172
200
  return result;
173
201
  }
174
202
 
@@ -178,18 +206,21 @@ class Hash
178
206
 
179
207
  def delete_if(&block)
180
208
  %x{
181
- var map = #{self}.map;
209
+ var map = #{self}.map, keys = #{self}.keys, value;
182
210
 
183
- for (var assoc in map) {
184
- var bucket = map[assoc],
185
- value;
211
+ for (var i = 0, length = keys.length; i < length; i++) {
212
+ var key = keys[i], obj = map[key];
186
213
 
187
- if ((value = block.call(__context, bucket[0], bucket[1])) === __breaker) {
214
+ if ((value = block.call(__context, key, obj)) === __breaker) {
188
215
  return __breaker.$v;
189
216
  }
190
217
 
191
218
  if (value !== false && value !== nil) {
192
- delete map[assoc];
219
+ keys.splice(i, 1);
220
+ delete map[key];
221
+
222
+ length--;
223
+ i--;
193
224
  }
194
225
  }
195
226
 
@@ -201,12 +232,12 @@ class Hash
201
232
 
202
233
  def each(&block)
203
234
  %x{
204
- var map = #{self}.map;
235
+ var map = #{self}.map, keys = #{self}.keys;
205
236
 
206
- for (var assoc in map) {
207
- var bucket = map[assoc];
237
+ for (var i = 0, length = keys.length; i < length; i++) {
238
+ var key = keys[i];
208
239
 
209
- if (block.call(__context, bucket[0], bucket[1]) === __breaker) {
240
+ if (block.call(__context, key, map[key]) === __breaker) {
210
241
  return __breaker.$v;
211
242
  }
212
243
  }
@@ -217,12 +248,12 @@ class Hash
217
248
 
218
249
  def each_key(&block)
219
250
  %x{
220
- var map = #{self}.map;
251
+ var keys = #{self}.keys;
221
252
 
222
- for (var assoc in map) {
223
- var bucket = map[assoc];
253
+ for (var i = 0, length = keys.length; i < length; i++) {
254
+ var key = keys[i];
224
255
 
225
- if (block.call(__context, bucket[0]) === __breaker) {
256
+ if (block.call(__context, key) === __breaker) {
226
257
  return __breaker.$v;
227
258
  }
228
259
  }
@@ -235,12 +266,10 @@ class Hash
235
266
 
236
267
  def each_value(&block)
237
268
  %x{
238
- var map = #{self}.map;
239
-
240
- for (var assoc in map) {
241
- var bucket = map[assoc];
269
+ var map = #{self}.map, keys = #{self}.keys;
242
270
 
243
- if (block.call(__context, bucket[1]) === __breaker) {
271
+ for (var i = 0, length = keys.length; i < length; i++) {
272
+ if (block.call(__context, map[keys[i]]) === __breaker) {
244
273
  return __breaker.$v;
245
274
  }
246
275
  }
@@ -251,11 +280,7 @@ class Hash
251
280
 
252
281
  def empty?
253
282
  %x{
254
- for (var assoc in #{self}.map) {
255
- return false;
256
- }
257
-
258
- return true;
283
+ return #{self}.keys.length === 0;
259
284
  }
260
285
  end
261
286
 
@@ -263,10 +288,10 @@ class Hash
263
288
 
264
289
  def fetch(key, defaults, &block)
265
290
  %x{
266
- var bucket = #{self}.map[key];
291
+ var value = #{self}.map[key];
267
292
 
268
- if (bucket) {
269
- return bucket[1];
293
+ if (value != null) {
294
+ return value;
270
295
  }
271
296
 
272
297
  if (block !== nil) {
@@ -287,15 +312,12 @@ class Hash
287
312
  }
288
313
  end
289
314
 
290
- def flatten(level)
315
+ def flatten(level=undefined)
291
316
  %x{
292
- var map = #{self}.map,
293
- result = [];
317
+ var map = #{self}.map, keys = #{self}.keys, result = [];
294
318
 
295
- for (var assoc in map) {
296
- var bucket = map[assoc],
297
- key = bucket[0],
298
- value = bucket[1];
319
+ for (var i = 0, length = keys.length; i < length; i++) {
320
+ var key = keys[i], value = map[key];
299
321
 
300
322
  result.push(key);
301
323
 
@@ -304,7 +326,7 @@ class Hash
304
326
  result.push(value);
305
327
  }
306
328
  else {
307
- result = result.concat(#{`value`.flatten(level - 1)});
329
+ result = result.concat(#{`value`.flatten(`level - 1`)});
308
330
  }
309
331
  }
310
332
  else {
@@ -317,13 +339,13 @@ class Hash
317
339
  end
318
340
 
319
341
  def has_key?(key)
320
- `!!#{self}.map[key]`
342
+ `#{self}.map[key] != null`
321
343
  end
322
344
 
323
345
  def has_value?(value)
324
346
  %x{
325
347
  for (var assoc in #{self}.map) {
326
- if (#{`#{self}.map[assoc][1]` == value}) {
348
+ if (#{`#{self}.map[assoc]` == value}) {
327
349
  return true;
328
350
  }
329
351
  }
@@ -340,11 +362,13 @@ class Hash
340
362
 
341
363
  def index(object)
342
364
  %x{
343
- for (var assoc in #{self}.map) {
344
- var bucket = #{self}.map[assoc];
365
+ var map = #{self}.map, keys = #{self}.keys;
366
+
367
+ for (var i = 0, length = keys.length; i < length; i++) {
368
+ var key = keys[i];
345
369
 
346
- if (#{object == `bucket[1]`}) {
347
- return bucket[0];
370
+ if (#{object == `map[key]`}) {
371
+ return key;
348
372
  }
349
373
  }
350
374
 
@@ -354,13 +378,13 @@ class Hash
354
378
 
355
379
  def indexes(*keys)
356
380
  %x{
357
- var result = [], map = #{self}.map, bucket;
381
+ var result = [], map = #{self}.map, val;
358
382
 
359
383
  for (var i = 0, length = keys.length; i < length; i++) {
360
- var key = keys[i];
384
+ var key = keys[i], val = map[key];
361
385
 
362
- if (bucket = map[key]) {
363
- result.push(bucket[1]);
386
+ if (val != null) {
387
+ result.push(val);
364
388
  }
365
389
  else {
366
390
  result.push(#{self}.none);
@@ -375,28 +399,27 @@ class Hash
375
399
 
376
400
  def inspect
377
401
  %x{
378
- var inspect = [],
379
- map = #{self}.map;
380
-
381
- for (var assoc in map) {
382
- var bucket = map[assoc];
402
+ var inspect = [], keys = #{self}.keys, map = #{self}.map;
383
403
 
384
- inspect.push(#{`bucket[0]`.inspect} + '=>' + #{`bucket[1]`.inspect});
404
+ for (var i = 0, length = keys.length; i < length; i++) {
405
+ var key = keys[i];
406
+ inspect.push(#{`key`.inspect} + '=>' + #{`map[key]`.inspect});
385
407
  }
408
+
386
409
  return '{' + inspect.join(', ') + '}';
387
410
  }
388
411
  end
389
412
 
390
413
  def invert
391
414
  %x{
392
- var result = __hash(),
393
- map = #{self}.map,
394
- map2 = result.map;
415
+ var result = __hash(), keys = #{self}.keys, map = #{self}.map,
416
+ keys2 = result.keys, map2 = result.map;
395
417
 
396
- for (var assoc in map) {
397
- var bucket = map[assoc];
418
+ for (var i = 0, length = keys.length; i < length; i++) {
419
+ var key = keys[i], obj = map[key];
398
420
 
399
- map2[bucket[1]] = [bucket[1], bucket[0]];
421
+ keys2.push(obj);
422
+ map2[obj] = key;
400
423
  }
401
424
 
402
425
  return result;
@@ -405,17 +428,21 @@ class Hash
405
428
 
406
429
  def keep_if(&block)
407
430
  %x{
408
- var map = #{self}.map, value;
431
+ var map = #{self}.map, keys = #{self}.keys, value;
409
432
 
410
- for (var assoc in map) {
411
- var bucket = map[assoc];
433
+ for (var i = 0, length = keys.length; i < length; i++) {
434
+ var key = keys[i], obj = map[key];
412
435
 
413
- if ((value = block.call(__context, bucket[0], bucket[1])) === __breaker) {
436
+ if ((value = block.call(__context, key, obj)) === __breaker) {
414
437
  return __breaker.$v;
415
438
  }
416
439
 
417
440
  if (value === false || value === nil) {
418
- delete map[assoc];
441
+ keys.splice(i, 1);
442
+ delete map[key];
443
+
444
+ length--;
445
+ i--;
419
446
  }
420
447
  }
421
448
 
@@ -429,25 +456,13 @@ class Hash
429
456
 
430
457
  def keys
431
458
  %x{
432
- var result = [];
433
-
434
- for (var assoc in #{self}.map) {
435
- result.push(#{self}.map[assoc][0]);
436
- }
437
-
438
- return result;
459
+ return #{self}.keys.slice(0);
439
460
  }
440
461
  end
441
462
 
442
463
  def length
443
464
  %x{
444
- var result = 0;
445
-
446
- for (var assoc in #{self}.map) {
447
- result++;
448
- }
449
-
450
- return result;
465
+ return #{self}.keys.length;
451
466
  }
452
467
  end
453
468
 
@@ -455,34 +470,40 @@ class Hash
455
470
 
456
471
  def merge(other, &block)
457
472
  %x{
458
- var result = __hash(),
459
- map = #{self}.map,
460
- map2 = result.map;
473
+ var keys = #{self}.keys, map = #{self}.map,
474
+ result = __hash(), keys2 = result.keys, map2 = result.map;
461
475
 
462
- for (var assoc in map) {
463
- var bucket = map[assoc];
476
+ for (var i = 0, length = keys.length; i < length; i++) {
477
+ var key = keys[i];
464
478
 
465
- map2[assoc] = [bucket[0], bucket[1]];
479
+ keys2.push(key);
480
+ map2[key] = map[key];
466
481
  }
467
482
 
468
- map = other.map;
483
+ var keys = other.keys, map = other.map;
469
484
 
470
485
  if (block === nil) {
471
- for (var assoc in map) {
472
- var bucket = map[assoc];
486
+ for (var i = 0, length = keys.length; i < length; i++) {
487
+ var key = keys[i];
488
+
489
+ if (map2[key] == null) {
490
+ keys2.push(key);
491
+ }
473
492
 
474
- map2[assoc] = [bucket[0], bucket[1]];
493
+ map2[key] = map[key];
475
494
  }
476
495
  }
477
496
  else {
478
- for (var assoc in map) {
479
- var bucket = map[assoc], key = bucket[0], val = bucket[1];
497
+ for (var i = 0, length = keys.length; i < length; i++) {
498
+ var key = keys[i];
480
499
 
481
- if (__hasOwn.call(map2, assoc)) {
482
- val = block.call(__context, key, map2[assoc][1], val);
500
+ if (map2[key] == null) {
501
+ keys2.push(key);
502
+ map2[key] = map[key];
503
+ }
504
+ else {
505
+ map2[key] = block.call(__context, key, map2[key], map[key]);
483
506
  }
484
-
485
- map2[assoc] = [key, val];
486
507
  }
487
508
  }
488
509
 
@@ -492,25 +513,31 @@ class Hash
492
513
 
493
514
  def merge!(other, &block)
494
515
  %x{
495
- var map = #{self}.map,
496
- map2 = other.map;
516
+ var keys = #{self}.keys, map = #{self}.map,
517
+ keys2 = other.keys, map2 = other.map;
497
518
 
498
519
  if (block === nil) {
499
- for (var assoc in map2) {
500
- var bucket = map2[assoc];
520
+ for (var i = 0, length = keys2.length; i < length; i++) {
521
+ var key = keys2[i];
501
522
 
502
- map[assoc] = [bucket[0], bucket[1]];
523
+ if (map[key] == null) {
524
+ keys.push(key);
525
+ }
526
+
527
+ map[key] = map2[key];
503
528
  }
504
529
  }
505
530
  else {
506
- for (var assoc in map2) {
507
- var bucket = map2[assoc], key = bucket[0], val = bucket[1];
531
+ for (var i = 0, length = keys2.length; i < length; i++) {
532
+ var key = keys2[i];
508
533
 
509
- if (__hasOwn.call(map, assoc)) {
510
- val = block.call(__context, key, map[assoc][1], val);
534
+ if (map[key] == null) {
535
+ keys.push(key);
536
+ map[key] = map2[key];
537
+ }
538
+ else {
539
+ map[key] = block.call(__context, key, map[key], map2[key]);
511
540
  }
512
-
513
- map[assoc] = [key, val];
514
541
  }
515
542
  }
516
543
 
@@ -520,13 +547,13 @@ class Hash
520
547
 
521
548
  def rassoc(object)
522
549
  %x{
523
- var map = #{self}.map;
550
+ var keys = #{self}.keys, map = #{self}.map;
524
551
 
525
- for (var assoc in map) {
526
- var bucket = map[assoc];
552
+ for (var i = 0, length = keys.length; i < length; i++) {
553
+ var key = keys[i], obj = map[key];
527
554
 
528
- if (#{`bucket[1]` == object}) {
529
- return [bucket[0], bucket[1]];
555
+ if (#{`obj` == object}) {
556
+ return [key, obj];
530
557
  }
531
558
  }
532
559
 
@@ -536,18 +563,19 @@ class Hash
536
563
 
537
564
  def reject(&block)
538
565
  %x{
539
- var map = #{self}.map, result = __hash(), map2 = result.map;
566
+ var keys = #{self}.keys, map = #{self}.map,
567
+ result = __hash(), map2 = result.map, keys2 = result.keys;
540
568
 
541
- for (var assoc in map) {
542
- var bucket = map[assoc],
543
- value;
569
+ for (var i = 0, length = keys.length; i < length; i++) {
570
+ var key = keys[i], obj = map[key], value;
544
571
 
545
- if ((value = block.call(__context, bucket[0], bucket[1])) === __breaker) {
572
+ if ((value = block.call(__context, key, obj)) === __breaker) {
546
573
  return __breaker.$v;
547
574
  }
548
575
 
549
576
  if (value === false || value === nil) {
550
- map2[bucket[0]] = [bucket[0], bucket[1]];
577
+ keys2.push(key);
578
+ map2[key] = obj;
551
579
  }
552
580
  }
553
581
 
@@ -557,12 +585,12 @@ class Hash
557
585
 
558
586
  def replace(other)
559
587
  %x{
560
- var map = #{self}.map = {};
561
-
562
- for (var assoc in other.map) {
563
- var bucket = other.map[assoc];
588
+ var map = #{self}.map = {}, keys = #{self}.keys = [];
564
589
 
565
- map[bucket[0]] = [bucket[0], bucket[1]];
590
+ for (var i = 0, length = other.keys.length; i < length; i++) {
591
+ var key = other.keys[i];
592
+ keys.push(key);
593
+ map[key] = other.map[key];
566
594
  }
567
595
 
568
596
  return #{self};
@@ -571,18 +599,19 @@ class Hash
571
599
 
572
600
  def select(&block)
573
601
  %x{
574
- var map = #{self}.map, result = __hash(), map2 = result.map;
602
+ var keys = #{self}.keys, map = #{self}.map,
603
+ result = __hash(), map2 = result.map, keys2 = result.keys;
575
604
 
576
- for (var assoc in map) {
577
- var bucket = map[assoc],
578
- value;
605
+ for (var i = 0, length = keys.length; i < length; i++) {
606
+ var key = keys[i], obj = map[key], value;
579
607
 
580
- if ((value = block.call(__context, bucket[0], bucket[1])) === __breaker) {
608
+ if ((value = block.call(__context, key, obj)) === __breaker) {
581
609
  return __breaker.$v;
582
610
  }
583
611
 
584
612
  if (value !== false && value !== nil) {
585
- map2[bucket[0]] = [bucket[0], bucket[1]];
613
+ keys2.push(key);
614
+ map2[key] = obj;
586
615
  }
587
616
  }
588
617
 
@@ -592,19 +621,22 @@ class Hash
592
621
 
593
622
  def select!(&block)
594
623
  %x{
595
- var map = #{self}.map, result = nil;
624
+ var map = #{self}.map, keys = #{self}.keys, value, result = nil;
596
625
 
597
- for (var assoc in map) {
598
- var bucket = map[assoc],
599
- value;
626
+ for (var i = 0, length = keys.length; i < length; i++) {
627
+ var key = keys[i], obj = map[key];
600
628
 
601
- if ((value = block.call(__context, bucket[0], bucket[1])) === __breaker) {
629
+ if ((value = block.call(__context, key, obj)) === __breaker) {
602
630
  return __breaker.$v;
603
631
  }
604
632
 
605
633
  if (value === false || value === nil) {
606
- delete map[assoc];
607
- result = #{self};
634
+ keys.splice(i, 1);
635
+ delete map[key];
636
+
637
+ length--;
638
+ i--;
639
+ result = #{self}
608
640
  }
609
641
  }
610
642
 
@@ -614,12 +646,15 @@ class Hash
614
646
 
615
647
  def shift
616
648
  %x{
617
- var map = #{self}.map;
649
+ var keys = #{self}.keys, map = #{self}.map;
618
650
 
619
- for (var assoc in map) {
620
- var bucket = map[assoc];
621
- delete map[assoc];
622
- return [bucket[0], bucket[1]];
651
+ if (keys.length) {
652
+ var key = keys[0], obj = map[key];
653
+
654
+ delete map[key];
655
+ keys.splice(0, 1);
656
+
657
+ return [key, obj];
623
658
  }
624
659
 
625
660
  return nil;
@@ -630,13 +665,11 @@ class Hash
630
665
 
631
666
  def to_a
632
667
  %x{
633
- var map = #{self}.map,
634
- result = [];
668
+ var keys = #{self}.keys, map = #{self}.map, result = [];
635
669
 
636
- for (var assoc in map) {
637
- var bucket = map[assoc];
638
-
639
- result.push([bucket[0], bucket[1]]);
670
+ for (var i = 0, length = keys.length; i < length; i++) {
671
+ var key = keys[i];
672
+ result.push([key, map[key]]);
640
673
  }
641
674
 
642
675
  return result;
@@ -649,30 +682,29 @@ class Hash
649
682
 
650
683
  def to_json
651
684
  %x{
652
- var parts = [], map = #{self}.map, bucket;
685
+ var inspect = [], keys = #{self}.keys, map = #{self}.map;
653
686
 
654
- for (var assoc in map) {
655
- bucket = map[assoc];
656
- parts.push(#{ `bucket[0]`.to_json } + ': ' + #{ `bucket[1]`.to_json });
687
+ for (var i = 0, length = keys.length; i < length; i++) {
688
+ var key = keys[i];
689
+ inspect.push(#{`key`.to_json} + ': ' + #{`map[key]`.to_json});
657
690
  }
658
691
 
659
- return '{' + parts.join(', ') + '}';
692
+ return '{' + inspect.join(', ') + '}';
660
693
  }
661
694
  end
662
695
 
663
696
  def to_native
664
697
  %x{
665
- var result = {}, map = #{self}.map, bucket, value;
698
+ var result = {}, keys = #{self}.keys, map = #{self}.map, bucket, value;
666
699
 
667
- for (var assoc in map) {
668
- bucket = map[assoc];
669
- value = bucket[1];
700
+ for (var i = 0, length = keys.length; i < length; i++) {
701
+ var key = keys[i], obj = map[key];
670
702
 
671
- if (value.$to_native) {
672
- result[assoc] = #{ `value`.to_native };
703
+ if (obj.$to_native) {
704
+ result[key] = #{`obj`.to_native};
673
705
  }
674
706
  else {
675
- result[assoc] = value;
707
+ result[key] = obj;
676
708
  }
677
709
  }
678
710
 
@@ -689,7 +721,7 @@ class Hash
689
721
  var map = #{self}.map;
690
722
 
691
723
  for (var assoc in map) {
692
- var v = map[assoc][1];
724
+ var v = map[assoc];
693
725
  if (#{`v` == value}) {
694
726
  return true;
695
727
  }
@@ -706,8 +738,8 @@ class Hash
706
738
  var map = #{self}.map,
707
739
  result = [];
708
740
 
709
- for (var assoc in map) {
710
- result.push(map[assoc][1]);
741
+ for (var key in map) {
742
+ result.push(map[key]);
711
743
  }
712
744
 
713
745
  return result;