opal 0.5.5 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (257) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +40 -9
  3. data/CHANGELOG.md +349 -0
  4. data/Gemfile +7 -8
  5. data/README.md +25 -3
  6. data/Rakefile +4 -2
  7. data/bin/opal +1 -1
  8. data/examples/rack/Gemfile +3 -0
  9. data/examples/rack/app/application.rb +13 -0
  10. data/examples/rack/app/user.rb +21 -0
  11. data/examples/rack/config.ru +7 -0
  12. data/examples/rack/index.html.erb +10 -0
  13. data/examples/sinatra/Gemfile +4 -0
  14. data/examples/sinatra/app/application.rb +7 -0
  15. data/examples/sinatra/config.ru +21 -0
  16. data/lib/mspec/opal/rake_task.rb +29 -8
  17. data/lib/mspec/opal/runner.rb +5 -4
  18. data/lib/opal.rb +1 -0
  19. data/lib/opal/builder.rb +0 -28
  20. data/lib/opal/cli.rb +0 -14
  21. data/lib/opal/compiler.rb +12 -11
  22. data/lib/opal/fragment.rb +8 -1
  23. data/lib/opal/nodes/array.rb +1 -1
  24. data/lib/opal/nodes/base.rb +4 -0
  25. data/lib/opal/nodes/call.rb +6 -2
  26. data/lib/opal/nodes/call_special.rb +1 -1
  27. data/lib/opal/nodes/class.rb +2 -2
  28. data/lib/opal/nodes/constants.rb +3 -1
  29. data/lib/opal/nodes/helpers.rb +23 -14
  30. data/lib/opal/nodes/if.rb +16 -9
  31. data/lib/opal/nodes/literal.rb +37 -5
  32. data/lib/opal/nodes/logic.rb +7 -1
  33. data/lib/opal/nodes/module.rb +2 -2
  34. data/lib/opal/nodes/scope.rb +13 -2
  35. data/lib/opal/nodes/top.rb +9 -0
  36. data/lib/opal/nodes/variables.rb +5 -2
  37. data/lib/opal/parser.rb +306 -71
  38. data/lib/opal/parser/grammar.rb +2667 -2775
  39. data/lib/opal/parser/grammar.y +177 -233
  40. data/lib/opal/parser/lexer.rb +511 -427
  41. data/lib/opal/parser/sexp.rb +15 -3
  42. data/lib/opal/source_map.rb +8 -4
  43. data/lib/opal/sprockets.rb +4 -0
  44. data/lib/opal/sprockets/cache_key_fix.rb +17 -0
  45. data/lib/opal/sprockets/environment.rb +21 -0
  46. data/lib/opal/sprockets/erb.rb +30 -0
  47. data/lib/opal/sprockets/processor.rb +127 -0
  48. data/lib/opal/sprockets/server.rb +166 -0
  49. data/lib/opal/util.rb +29 -0
  50. data/lib/opal/version.rb +1 -1
  51. data/opal.gemspec +1 -1
  52. data/opal/corelib/array.rb +106 -187
  53. data/opal/corelib/array/inheritance.rb +113 -0
  54. data/opal/corelib/basic_object.rb +6 -2
  55. data/opal/corelib/boolean.rb +4 -0
  56. data/opal/corelib/class.rb +2 -0
  57. data/opal/corelib/complex.rb +3 -0
  58. data/opal/corelib/enumerable.rb +75 -8
  59. data/opal/corelib/enumerator.rb +2 -0
  60. data/opal/corelib/error.rb +23 -23
  61. data/opal/corelib/hash.rb +5 -5
  62. data/opal/corelib/helpers.rb +51 -16
  63. data/opal/corelib/io.rb +7 -24
  64. data/opal/corelib/kernel.rb +23 -11
  65. data/opal/corelib/module.rb +44 -47
  66. data/opal/corelib/nil_class.rb +4 -0
  67. data/opal/corelib/numeric.rb +101 -15
  68. data/opal/corelib/range.rb +2 -0
  69. data/opal/corelib/rational.rb +3 -0
  70. data/opal/corelib/regexp.rb +36 -17
  71. data/opal/corelib/runtime.js +22 -7
  72. data/opal/corelib/string.rb +213 -110
  73. data/opal/corelib/string/inheritance.rb +78 -0
  74. data/opal/corelib/struct.rb +8 -0
  75. data/opal/corelib/time.rb +54 -42
  76. data/opal/corelib/variables.rb +24 -0
  77. data/opal/opal.rb +5 -27
  78. data/spec/cli/compiler_spec.rb +136 -0
  79. data/spec/cli/dependency_resolver_spec.rb +40 -0
  80. data/spec/cli/lexer_spec.rb +110 -0
  81. data/spec/cli/parser/alias_spec.rb +26 -0
  82. data/spec/cli/parser/and_spec.rb +13 -0
  83. data/spec/cli/parser/attrasgn_spec.rb +28 -0
  84. data/spec/cli/parser/begin_spec.rb +42 -0
  85. data/spec/cli/parser/block_spec.rb +12 -0
  86. data/spec/cli/parser/break_spec.rb +17 -0
  87. data/spec/cli/parser/call_spec.rb +139 -0
  88. data/spec/cli/parser/class_spec.rb +35 -0
  89. data/spec/cli/parser/comments_spec.rb +11 -0
  90. data/spec/cli/parser/def_spec.rb +61 -0
  91. data/spec/cli/parser/if_spec.rb +26 -0
  92. data/spec/cli/parser/iter_spec.rb +59 -0
  93. data/spec/cli/parser/lambda_spec.rb +64 -0
  94. data/spec/cli/parser/literal_spec.rb +113 -0
  95. data/spec/cli/parser/masgn_spec.rb +37 -0
  96. data/spec/cli/parser/module_spec.rb +27 -0
  97. data/spec/cli/parser/not_spec.rb +27 -0
  98. data/spec/cli/parser/op_asgn1_spec.rb +23 -0
  99. data/spec/cli/parser/op_asgn2_spec.rb +23 -0
  100. data/spec/cli/parser/or_spec.rb +13 -0
  101. data/spec/cli/parser/return_spec.rb +17 -0
  102. data/spec/cli/parser/sclass_spec.rb +21 -0
  103. data/spec/cli/parser/string_spec.rb +269 -0
  104. data/spec/cli/parser/super_spec.rb +20 -0
  105. data/spec/cli/parser/undef_spec.rb +15 -0
  106. data/spec/cli/parser/unless_spec.rb +13 -0
  107. data/spec/cli/parser/variables_spec.rb +92 -0
  108. data/spec/cli/parser/while_spec.rb +15 -0
  109. data/spec/cli/parser/yield_spec.rb +20 -0
  110. data/spec/cli/spec_helper.rb +31 -11
  111. data/spec/opal/core/array/set_range_to_array_spec.rb +7 -0
  112. data/spec/opal/core/date_spec.rb +122 -0
  113. data/spec/opal/core/language/predefined_spec.rb +1 -1
  114. data/spec/opal/core/runtime/operator_call_spec.rb +13 -0
  115. data/spec/opal/core/runtime/truthy_spec.rb +23 -0
  116. data/spec/opal/filters/bugs/array.rb +96 -87
  117. data/spec/opal/filters/bugs/basic_object.rb +9 -0
  118. data/spec/opal/filters/bugs/class.rb +16 -0
  119. data/spec/opal/filters/bugs/enumerable.rb +54 -0
  120. data/spec/opal/filters/bugs/language.rb +37 -3
  121. data/spec/opal/filters/bugs/math.rb +93 -0
  122. data/spec/opal/filters/bugs/nil.rb +7 -0
  123. data/spec/opal/filters/bugs/numeric.rb +19 -0
  124. data/spec/opal/filters/bugs/opal.rb +12 -0
  125. data/spec/opal/filters/bugs/regexp.rb +0 -2
  126. data/spec/opal/filters/bugs/string.rb +317 -19
  127. data/spec/opal/filters/bugs/struct.rb +29 -0
  128. data/spec/opal/filters/bugs/time.rb +130 -9
  129. data/spec/opal/filters/unsupported/encoding.rb +52 -4
  130. data/spec/opal/filters/unsupported/enumerator.rb +0 -3
  131. data/spec/opal/filters/unsupported/integer_size.rb +7 -0
  132. data/spec/opal/filters/unsupported/method_added.rb +10 -0
  133. data/spec/opal/filters/unsupported/mutable_strings.rb +299 -1
  134. data/spec/opal/filters/unsupported/private_constants.rb +30 -0
  135. data/spec/opal/filters/unsupported/private_methods.rb +16 -0
  136. data/spec/opal/filters/unsupported/random.rb +4 -0
  137. data/spec/opal/filters/unsupported/tainted.rb +53 -0
  138. data/spec/opal/filters/unsupported/trusted.rb +5 -0
  139. data/spec/opal/rubyspecs +167 -234
  140. data/spec/opal/spec_helper.rb +3 -0
  141. data/spec/opal/stdlib/promise/error_spec.rb +15 -0
  142. data/spec/opal/stdlib/promise/rescue_spec.rb +35 -0
  143. data/spec/opal/stdlib/promise/then_spec.rb +54 -0
  144. data/spec/opal/stdlib/promise/trace_spec.rb +35 -0
  145. data/spec/opal/stdlib/promise/value_spec.rb +15 -0
  146. data/spec/opal/stdlib/promise/when_spec.rb +34 -0
  147. data/stdlib/base64.rb +152 -0
  148. data/stdlib/date.rb +82 -49
  149. data/{opal/corelib → stdlib}/encoding.rb +3 -1
  150. data/stdlib/erb.rb +0 -1
  151. data/stdlib/json.rb +10 -26
  152. data/stdlib/math.rb +370 -0
  153. data/stdlib/native.rb +40 -33
  154. data/stdlib/opal-parser.rb +7 -4
  155. data/stdlib/promise.rb +292 -0
  156. data/stdlib/strscan.rb +1 -1
  157. data/stdlib/template.rb +1 -3
  158. data/stdlib/time.rb +9 -0
  159. metadata +143 -204
  160. data/doc/compiler.md +0 -42
  161. data/doc/compiler_options.md +0 -5
  162. data/doc/examples/node_http_server.rb +0 -49
  163. data/doc/external_libraries.md +0 -9
  164. data/doc/generated_javascript.md +0 -272
  165. data/doc/home.md +0 -17
  166. data/doc/method_missing.md +0 -58
  167. data/doc/static_applications.md +0 -60
  168. data/doc/using_ruby_from_javascript.md +0 -18
  169. data/doc/using_sprockets.md +0 -65
  170. data/spec/opal/core/numeric/abs_spec.rb +0 -12
  171. data/spec/opal/core/numeric/downto_spec.rb +0 -19
  172. data/spec/opal/core/numeric/equal_value_spec.rb +0 -9
  173. data/spec/opal/core/numeric/even_spec.rb +0 -21
  174. data/spec/opal/core/numeric/magnitude_spec.rb +0 -12
  175. data/spec/opal/core/numeric/odd_spec.rb +0 -21
  176. data/spec/opal/core/string/chop_spec.rb +0 -10
  177. data/spec/opal/core/string/chr_spec.rb +0 -13
  178. data/spec/opal/core/string/clone_spec.rb +0 -8
  179. data/spec/opal/core/string/comparison_spec.rb +0 -13
  180. data/spec/opal/core/string/dup_spec.rb +0 -8
  181. data/spec/opal/core/string/element_reference_spec.rb +0 -96
  182. data/spec/opal/core/string/fixtures/classes.rb +0 -49
  183. data/spec/opal/core/string/format_spec.rb +0 -9
  184. data/spec/opal/core/string/freeze_spec.rb +0 -15
  185. data/spec/opal/core/string/gsub_spec.rb +0 -31
  186. data/spec/opal/core/string/lines_spec.rb +0 -9
  187. data/spec/opal/core/string/ljust_spec.rb +0 -32
  188. data/spec/opal/core/string/lstrip_spec.rb +0 -7
  189. data/spec/opal/core/string/match_spec.rb +0 -49
  190. data/spec/opal/core/string/next_spec.rb +0 -10
  191. data/spec/opal/core/string/ord_spec.rb +0 -9
  192. data/spec/opal/core/string/partition_spec.rb +0 -10
  193. data/spec/opal/core/string/rindex_spec.rb +0 -50
  194. data/spec/opal/core/string/rjust_spec.rb +0 -32
  195. data/spec/opal/core/string/rstrip_spec.rb +0 -7
  196. data/spec/opal/core/string/scan_spec.rb +0 -66
  197. data/spec/opal/core/string/slice_spec.rb +0 -74
  198. data/spec/opal/core/string/split_spec.rb +0 -5
  199. data/spec/opal/core/string/strip_spec.rb +0 -6
  200. data/spec/opal/core/string/sub_spec.rb +0 -38
  201. data/spec/opal/core/string/succ_spec.rb +0 -10
  202. data/spec/opal/core/string/sum_spec.rb +0 -5
  203. data/spec/opal/core/string/to_f_spec.rb +0 -14
  204. data/spec/opal/core/string/to_i_spec.rb +0 -25
  205. data/spec/opal/core/string/tr_s_spec.rb +0 -31
  206. data/spec/opal/core/string/tr_spec.rb +0 -31
  207. data/spec/opal/filters/bugs/parser.rb +0 -10
  208. data/spec/opal/filters/unsupported/immutable_strings.rb +0 -24
  209. data/spec/opal/filters/unsupported/string_subclasses.rb +0 -8
  210. data/spec/opal/parser/alias_spec.rb +0 -26
  211. data/spec/opal/parser/and_spec.rb +0 -13
  212. data/spec/opal/parser/array_spec.rb +0 -22
  213. data/spec/opal/parser/attrasgn_spec.rb +0 -28
  214. data/spec/opal/parser/begin_spec.rb +0 -42
  215. data/spec/opal/parser/block_spec.rb +0 -12
  216. data/spec/opal/parser/break_spec.rb +0 -17
  217. data/spec/opal/parser/call_spec.rb +0 -131
  218. data/spec/opal/parser/class_spec.rb +0 -35
  219. data/spec/opal/parser/const_spec.rb +0 -13
  220. data/spec/opal/parser/cvar_spec.rb +0 -11
  221. data/spec/opal/parser/def_spec.rb +0 -61
  222. data/spec/opal/parser/false_spec.rb +0 -17
  223. data/spec/opal/parser/file_spec.rb +0 -7
  224. data/spec/opal/parser/gvar_spec.rb +0 -13
  225. data/spec/opal/parser/hash_spec.rb +0 -17
  226. data/spec/opal/parser/heredoc_spec.rb +0 -30
  227. data/spec/opal/parser/iasgn_spec.rb +0 -9
  228. data/spec/opal/parser/if_spec.rb +0 -26
  229. data/spec/opal/parser/int_spec.rb +0 -13
  230. data/spec/opal/parser/iter_spec.rb +0 -59
  231. data/spec/opal/parser/ivar_spec.rb +0 -9
  232. data/spec/opal/parser/lambda_spec.rb +0 -64
  233. data/spec/opal/parser/lasgn_spec.rb +0 -8
  234. data/spec/opal/parser/line_spec.rb +0 -8
  235. data/spec/opal/parser/lvar_spec.rb +0 -38
  236. data/spec/opal/parser/masgn_spec.rb +0 -37
  237. data/spec/opal/parser/module_spec.rb +0 -27
  238. data/spec/opal/parser/nil_spec.rb +0 -17
  239. data/spec/opal/parser/not_spec.rb +0 -27
  240. data/spec/opal/parser/nth_ref_spec.rb +0 -13
  241. data/spec/opal/parser/op_asgn1_spec.rb +0 -23
  242. data/spec/opal/parser/op_asgn2_spec.rb +0 -23
  243. data/spec/opal/parser/or_spec.rb +0 -13
  244. data/spec/opal/parser/parse_spec.rb +0 -66
  245. data/spec/opal/parser/regexp_spec.rb +0 -16
  246. data/spec/opal/parser/return_spec.rb +0 -17
  247. data/spec/opal/parser/sclass_spec.rb +0 -21
  248. data/spec/opal/parser/self_spec.rb +0 -17
  249. data/spec/opal/parser/str_spec.rb +0 -107
  250. data/spec/opal/parser/string_spec.rb +0 -8
  251. data/spec/opal/parser/super_spec.rb +0 -20
  252. data/spec/opal/parser/true_spec.rb +0 -17
  253. data/spec/opal/parser/undef_spec.rb +0 -15
  254. data/spec/opal/parser/unless_spec.rb +0 -13
  255. data/spec/opal/parser/while_spec.rb +0 -15
  256. data/spec/opal/parser/xstr_spec.rb +0 -116
  257. data/spec/opal/parser/yield_spec.rb +0 -20
@@ -1,3 +1,5 @@
1
+ require 'corelib/enumerable'
2
+
1
3
  class Range
2
4
  include Enumerable
3
5
 
@@ -0,0 +1,3 @@
1
+ class Rational < Numeric
2
+
3
+ end
@@ -1,16 +1,26 @@
1
1
  class Regexp
2
2
  `def._isRegexp = true`
3
3
 
4
- def self.escape(string)
5
- `string.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\^\\$\\| ]/g, '\\\\$&')`
6
- end
4
+ class << self
5
+ def escape(string)
6
+ %x{
7
+ return string.replace(/([-[\]/{}()*+?.^$\\| ])/g, '\\$1')
8
+ .replace(/[\n]/g, '\\n')
9
+ .replace(/[\r]/g, '\\r')
10
+ .replace(/[\f]/g, '\\f')
11
+ .replace(/[\t]/g, '\\t');
12
+ }
13
+ end
7
14
 
8
- def self.union(*parts)
9
- `new RegExp(parts.join(''))`
10
- end
15
+ alias quote escape
11
16
 
12
- def self.new(regexp, options = undefined)
13
- `new RegExp(regexp, options)`
17
+ def union(*parts)
18
+ `new RegExp(parts.join(''))`
19
+ end
20
+
21
+ def new(regexp, options = undefined)
22
+ `new RegExp(regexp, options)`
23
+ end
14
24
  end
15
25
 
16
26
  def ==(other)
@@ -18,15 +28,17 @@ class Regexp
18
28
  end
19
29
 
20
30
  def ===(str)
21
- if `str._isString == null` && str.respond_to?(:to_str)
22
- str = str.to_str
23
- end
31
+ %x{
32
+ if (!str._isString && #{str.respond_to?(:to_str)}) {
33
+ #{str = str.to_str};
34
+ }
24
35
 
25
- if `str._isString == null`
26
- return false
27
- end
36
+ if (!str._isString) {
37
+ return false;
38
+ }
28
39
 
29
- `self.test(str)`
40
+ return self.test(str);
41
+ }
30
42
  end
31
43
 
32
44
  def =~(string)
@@ -69,7 +81,7 @@ class Regexp
69
81
  `self.toString()`
70
82
  end
71
83
 
72
- def match(string, pos = undefined)
84
+ def match(string, pos = undefined, &block)
73
85
  if `string === nil`
74
86
  $~ = $` = $' = nil
75
87
 
@@ -98,7 +110,14 @@ class Regexp
98
110
  var result = re.exec(string);
99
111
 
100
112
  if (result) {
101
- return #{$~ = MatchData.new(`re`, `result`)};
113
+ result = #{$~ = MatchData.new(`re`, `result`)};
114
+
115
+ if (block === nil) {
116
+ return result;
117
+ }
118
+ else {
119
+ return #{block.call(`result`)};
120
+ }
102
121
  }
103
122
  else {
104
123
  return #{$~ = $` = $' = nil};
@@ -614,6 +614,12 @@
614
614
  return true;
615
615
  }
616
616
 
617
+ for (var i = 0, length = search.__inc__.length; i < length; i++) {
618
+ if (search.__inc__[i] == klass) {
619
+ return true;
620
+ }
621
+ }
622
+
617
623
  search = search._super;
618
624
  }
619
625
 
@@ -751,17 +757,26 @@
751
757
  hash.map = assocs;
752
758
  hash.keys = keys;
753
759
 
754
- if (arguments.length == 1 && arguments[0]._isArray) {
755
- var args = arguments[0];
760
+ if (arguments.length == 1) {
761
+ if (arguments[0]._isArray) {
762
+ var args = arguments[0];
756
763
 
757
- for (var i = 0, length = args.length; i < length; i++) {
758
- var key = args[i][0], obj = args[i][1];
764
+ for (var i = 0, length = args.length; i < length; i++) {
765
+ var key = args[i][0], obj = args[i][1];
759
766
 
760
- if (assocs[key] == null) {
767
+ if (assocs[key] == null) {
768
+ keys.push(key);
769
+ }
770
+
771
+ assocs[key] = obj;
772
+ }
773
+ }
774
+ else {
775
+ var obj = arguments[0];
776
+ for (var key in obj) {
777
+ assocs[key] = obj[key];
761
778
  keys.push(key);
762
779
  }
763
-
764
- assocs[key] = obj;
765
780
  }
766
781
  }
767
782
  else {
@@ -1,3 +1,5 @@
1
+ require 'corelib/comparable'
2
+
1
3
  class String
2
4
  include Comparable
3
5
 
@@ -69,9 +71,12 @@ class String
69
71
  end
70
72
 
71
73
  def ==(other)
72
- `!!(other._isString && self.valueOf() === other.valueOf())`
74
+ return false unless String === other
75
+
76
+ `#{to_s} == #{other.to_s}`
73
77
  end
74
78
 
79
+ alias eql? ==
75
80
  alias === ==
76
81
 
77
82
  def =~(other)
@@ -166,8 +171,10 @@ class String
166
171
  }
167
172
  end
168
173
 
169
- def chars
170
- each_char.to_a
174
+ def chars(&block)
175
+ return each_char.to_a unless block
176
+
177
+ each_char(&block)
171
178
  end
172
179
 
173
180
  def chomp(separator = $/)
@@ -176,14 +183,14 @@ class String
176
183
  separator = Opal.coerce_to!(separator, String, :to_str).to_s
177
184
 
178
185
  %x{
179
- if (separator === "\\n") {
180
- return self.replace(/\\r?\\n?$/, '');
186
+ if (separator === "\n") {
187
+ return self.replace(/\r?\n?$/, '');
181
188
  }
182
189
  else if (separator === "") {
183
- return self.replace(/(\\r?\\n)+$/, '');
190
+ return self.replace(/(\r?\n)+$/, '');
184
191
  }
185
192
  else if (self.length > separator.length) {
186
- var tail = self.substr(-1 * separator.length);
193
+ var tail = self.substr(self.length - separator.length, separator.length);
187
194
 
188
195
  if (tail === separator) {
189
196
  return self.substr(0, self.length - separator.length);
@@ -202,7 +209,7 @@ class String
202
209
  return "";
203
210
  }
204
211
 
205
- if (self.charAt(length - 1) === "\\n" && self.charAt(length - 2) === "\\r") {
212
+ if (self.charAt(length - 1) === "\n" && self.charAt(length - 2) === "\r") {
206
213
  return self.substr(0, length - 2);
207
214
  }
208
215
  else {
@@ -216,7 +223,15 @@ class String
216
223
  end
217
224
 
218
225
  def clone
219
- `self.slice()`
226
+ copy = `self.slice()`
227
+ copy.initialize_clone(self)
228
+ copy
229
+ end
230
+
231
+ def dup
232
+ copy = `self.slice()`
233
+ copy.initialize_dup(self)
234
+ copy
220
235
  end
221
236
 
222
237
  def count(str)
@@ -269,9 +284,10 @@ class String
269
284
  def end_with?(*suffixes)
270
285
  %x{
271
286
  for (var i = 0, length = suffixes.length; i < length; i++) {
272
- var suffix = #{Opal.coerce_to `suffixes[i]`, String, :to_str};
287
+ var suffix = #{Opal.coerce_to(`suffixes[i]`, String, :to_str).to_s};
273
288
 
274
- if (self.length >= suffix.length && self.substr(0 - suffix.length) === suffix) {
289
+ if (self.length >= suffix.length &&
290
+ self.substr(self.length - suffix.length, suffix.length) == suffix) {
275
291
  return true;
276
292
  }
277
293
  }
@@ -297,13 +313,13 @@ class String
297
313
  options = pattern.substr(pattern.lastIndexOf('/') + 1) + 'g',
298
314
  regexp = pattern.substr(1, pattern.lastIndexOf('/') - 1);
299
315
 
300
- #{self}.$sub._p = block;
301
- return #{self}.$sub(new RegExp(regexp, options), replace);
316
+ self.$sub._p = block;
317
+ return self.$sub(new RegExp(regexp, options), replace);
302
318
  }
303
319
  end
304
320
 
305
321
  def hash
306
- `#{self}.toString()`
322
+ `self.toString()`
307
323
  end
308
324
 
309
325
  def hex
@@ -376,15 +392,15 @@ class String
376
392
 
377
393
  def inspect
378
394
  %x{
379
- var escapable = /[\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,
395
+ var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
380
396
  meta = {
381
- '\\b': '\\\\b',
382
- '\\t': '\\\\t',
383
- '\\n': '\\\\n',
384
- '\\f': '\\\\f',
385
- '\\r': '\\\\r',
386
- '"' : '\\\\"',
387
- '\\\\': '\\\\\\\\'
397
+ '\b': '\\b',
398
+ '\t': '\\t',
399
+ '\n': '\\n',
400
+ '\f': '\\f',
401
+ '\r': '\\r',
402
+ '"' : '\\"',
403
+ '\\': '\\\\'
388
404
  };
389
405
 
390
406
  escapable.lastIndex = 0;
@@ -393,7 +409,7 @@ class String
393
409
  var c = meta[a];
394
410
 
395
411
  return typeof c === 'string' ? c :
396
- '\\\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
412
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
397
413
  }) + '"' : '"' + self + '"';
398
414
  }
399
415
  end
@@ -435,7 +451,7 @@ class String
435
451
  end
436
452
 
437
453
  def lstrip
438
- `self.replace(/^\\s*/, '')`
454
+ `self.replace(/^\s*/, '')`
439
455
  end
440
456
 
441
457
  def match(pattern, pos = undefined, &block)
@@ -452,32 +468,32 @@ class String
452
468
 
453
469
  def next
454
470
  %x{
455
- if (#{self}.length === 0) {
471
+ if (self.length === 0) {
456
472
  return "";
457
473
  }
458
474
 
459
- var initial = #{self}.substr(0, #{self}.length - 1);
460
- var last = String.fromCharCode(#{self}.charCodeAt(#{self}.length - 1) + 1);
475
+ var initial = self.substr(0, self.length - 1);
476
+ var last = String.fromCharCode(self.charCodeAt(self.length - 1) + 1);
461
477
 
462
478
  return initial + last;
463
479
  }
464
480
  end
465
481
 
466
482
  def ord
467
- `#{self}.charCodeAt(0)`
483
+ `self.charCodeAt(0)`
468
484
  end
469
485
 
470
486
  def partition(str)
471
487
  %x{
472
- var result = #{self}.split(str);
473
- var splitter = (result[0].length === #{self}.length ? "" : str);
488
+ var result = self.split(str);
489
+ var splitter = (result[0].length === self.length ? "" : str);
474
490
 
475
491
  return [result[0], splitter, result.slice(1).join(str.toString())];
476
492
  }
477
493
  end
478
494
 
479
495
  def reverse
480
- `#{self}.split('').reverse().join('')`
496
+ `self.split('').reverse().join('')`
481
497
  end
482
498
 
483
499
  # TODO handle case where search is regexp
@@ -489,21 +505,21 @@ class String
489
505
  #{raise TypeError.new(`msg`)};
490
506
  }
491
507
 
492
- if (#{self}.length == 0) {
508
+ if (self.length == 0) {
493
509
  return search.length == 0 ? 0 : nil;
494
510
  }
495
511
 
496
512
  var result = -1;
497
513
  if (offset != null) {
498
514
  if (offset < 0) {
499
- offset = #{self}.length + offset;
515
+ offset = self.length + offset;
500
516
  }
501
517
 
502
518
  if (search_type == String) {
503
- result = #{self}.lastIndexOf(search, offset);
519
+ result = self.lastIndexOf(search, offset);
504
520
  }
505
521
  else {
506
- result = #{self}.substr(0, offset + 1).$reverse().search(search);
522
+ result = self.substr(0, offset + 1).$reverse().search(search);
507
523
  if (result !== -1) {
508
524
  result = offset - result;
509
525
  }
@@ -511,12 +527,12 @@ class String
511
527
  }
512
528
  else {
513
529
  if (search_type == String) {
514
- result = #{self}.lastIndexOf(search);
530
+ result = self.lastIndexOf(search);
515
531
  }
516
532
  else {
517
- result = #{self}.$reverse().search(search);
533
+ result = self.$reverse().search(search);
518
534
  if (result !== -1) {
519
- result = #{self}.length - 1 - result;
535
+ result = self.length - 1 - result;
520
536
  }
521
537
  }
522
538
  }
@@ -546,7 +562,7 @@ class String
546
562
  end
547
563
 
548
564
  def rstrip
549
- `self.replace(/\\s*$/, '')`
565
+ `self.replace(/\s*$/, '')`
550
566
  end
551
567
 
552
568
  def scan(pattern, &block)
@@ -563,17 +579,17 @@ class String
563
579
  var result = [];
564
580
  var match;
565
581
 
566
- while ((match = pattern.exec(#{self})) != null) {
582
+ while ((match = pattern.exec(self)) != null) {
567
583
  var match_data = #{MatchData.new `pattern`, `match`};
568
584
  if (block === nil) {
569
585
  match.length == 1 ? result.push(match[0]) : result.push(match.slice(1));
570
586
  }
571
587
  else {
572
- match.length == 1 ? block(match[0]) : block.apply(#{self}, match.slice(1));
588
+ match.length == 1 ? block(match[0]) : block.apply(self, match.slice(1));
573
589
  }
574
590
  }
575
591
 
576
- return (block !== nil ? #{self} : result);
592
+ return (block !== nil ? self : result);
577
593
  }
578
594
  end
579
595
 
@@ -582,13 +598,101 @@ class String
582
598
  alias slice []
583
599
 
584
600
  def split(pattern = $; || ' ', limit = undefined)
585
- `#{self}.split(pattern, limit)`
601
+ %x{
602
+ if (pattern && pattern._isRegexp) {
603
+ return self.split(pattern, limit);
604
+ } else {
605
+ result = [],
606
+ splitted = start = lim = 0,
607
+ splat = #{Opal.try_convert(pattern, String, :to_str).to_s};
608
+
609
+ if (undefined !== limit) {
610
+ lim = #{Opal.try_convert(limit, Integer, :to_int)};
611
+ }
612
+
613
+ if (pattern === nil) {
614
+ if (#{$;} === undefined || #{$;} === nil) {
615
+ splat = ' ';
616
+ }
617
+ else {
618
+ splat = #{$;};
619
+ }
620
+ }
621
+
622
+ if (lim == 1) {
623
+ if (self.length == 0) {
624
+ return [];
625
+ }
626
+ else {
627
+ return [self];
628
+ }
629
+ }
630
+
631
+ string = (splat == ' ') ? self.replace(/[\r\n\t\v]\s+/g, ' ')
632
+ : self;
633
+
634
+ while ((cursor = string.indexOf(splat, start)) > -1 && cursor < string.length) {
635
+ if (splitted + 1 == lim) {
636
+ break;
637
+ }
638
+
639
+ if (splat == ' ' && cursor == start) {
640
+ start = cursor + 1;
641
+ continue;
642
+ }
643
+
644
+ result.push(string.substr(start, splat.length ? cursor - start : 1));
645
+ splitted++;
646
+
647
+ start = cursor + (splat.length ? splat.length : 1);
648
+ }
649
+
650
+ if (string.length > 0 && (limit || lim < 0 || string.length > start)) {
651
+ if (string.length == start) {
652
+ result.push('');
653
+ }
654
+ else {
655
+ result.push(string.substr(start, string.length));
656
+ }
657
+ }
658
+
659
+ if (limit === undefined || lim == 0) {
660
+ while (result.length > 0 && result[result.length - 1].length == 0) {
661
+ result.pop();
662
+ }
663
+ }
664
+
665
+ return result;
666
+ }
667
+ }
668
+ end
669
+
670
+ def squeeze(*sets)
671
+ %x{
672
+ if (sets.length === 0) {
673
+ return self.replace(/(.)\1+/g, '$1');
674
+ }
675
+ }
676
+
677
+ %x{
678
+ var set = #{Opal.coerce_to(`sets[0]`, String, :to_str).chars};
679
+
680
+ for (var i = 1, length = sets.length; i < length; i++) {
681
+ set = #{`set` & Opal.coerce_to(`sets[i]`, String, :to_str).chars};
682
+ }
683
+
684
+ if (set.length === 0) {
685
+ return self;
686
+ }
687
+
688
+ return self.replace(new RegExp("([" + #{Regexp.escape(`set`.join)} + "])\\1+", "g"), "$1");
689
+ }
586
690
  end
587
691
 
588
692
  def start_with?(*prefixes)
589
693
  %x{
590
694
  for (var i = 0, length = prefixes.length; i < length; i++) {
591
- var prefix = #{Opal.coerce_to `prefixes[i]`, String, :to_str};
695
+ var prefix = #{Opal.coerce_to(`prefixes[i]`, String, :to_str).to_s};
592
696
 
593
697
  if (self.indexOf(prefix) === 0) {
594
698
  return true;
@@ -600,18 +704,18 @@ class String
600
704
  end
601
705
 
602
706
  def strip
603
- `#{self}.replace(/^\\s*/, '').replace(/\\s*$/, '')`
707
+ `self.replace(/^\s*/, '').replace(/\s*$/, '')`
604
708
  end
605
709
 
606
710
  def sub(pattern, replace = undefined, &block)
607
711
  %x{
608
712
  if (typeof(replace) === 'string') {
609
713
  // convert Ruby back reference to JavaScript back reference
610
- replace = replace.replace(/\\\\([1-9])/g, '$$$1')
611
- return #{self}.replace(pattern, replace);
714
+ replace = replace.replace(/\\([1-9])/g, '$$$1')
715
+ return self.replace(pattern, replace);
612
716
  }
613
717
  if (block !== nil) {
614
- return #{self}.replace(pattern, function() {
718
+ return self.replace(pattern, function() {
615
719
  // FIXME: this should be a formal MatchData object with all the goodies
616
720
  var match_data = []
617
721
  for (var i = 0, len = arguments.length; i < len; i++) {
@@ -639,7 +743,7 @@ class String
639
743
  }
640
744
  else if (replace !== undefined) {
641
745
  if (#{replace.is_a?(Hash)}) {
642
- return #{self}.replace(pattern, function(str) {
746
+ return self.replace(pattern, function(str) {
643
747
  var value = #{replace[str]};
644
748
 
645
749
  return (value == null) ? nil : #{value.to_s};
@@ -652,13 +756,13 @@ class String
652
756
  #{raise TypeError, "can't convert #{replace.class} into String"};
653
757
  }
654
758
 
655
- return #{self}.replace(pattern, replace);
759
+ return self.replace(pattern, replace);
656
760
  }
657
761
  }
658
762
  else {
659
763
  // convert Ruby back reference to JavaScript back reference
660
- replace = replace.toString().replace(/\\\\([1-9])/g, '$$$1')
661
- return #{self}.replace(pattern, replace);
764
+ replace = replace.toString().replace(/\\([1-9])/g, '$$$1')
765
+ return self.replace(pattern, replace);
662
766
  }
663
767
  }
664
768
  end
@@ -669,8 +773,8 @@ class String
669
773
  %x{
670
774
  var result = 0;
671
775
 
672
- for (var i = 0, length = #{self}.length; i < length; i++) {
673
- result += (#{self}.charCodeAt(i) % ((1 << n) - 1));
776
+ for (var i = 0, length = self.length; i < length; i++) {
777
+ result += (self.charCodeAt(i) % ((1 << n) - 1));
674
778
  }
675
779
 
676
780
  return result;
@@ -679,11 +783,11 @@ class String
679
783
 
680
784
  def swapcase
681
785
  %x{
682
- var str = #{self}.replace(/([a-z]+)|([A-Z]+)/g, function($0,$1,$2) {
786
+ var str = self.replace(/([a-z]+)|([A-Z]+)/g, function($0,$1,$2) {
683
787
  return $1 ? $0.toUpperCase() : $0.toLowerCase();
684
788
  });
685
789
 
686
- if (#{self}.constructor === String) {
790
+ if (self.constructor === String) {
687
791
  return str;
688
792
  }
689
793
 
@@ -691,27 +795,26 @@ class String
691
795
  }
692
796
  end
693
797
 
694
- def to_a
798
+ def to_f
695
799
  %x{
696
- if (#{self}.length === 0) {
697
- return [];
800
+ if (self.charAt(0) === '_') {
801
+ return 0;
698
802
  }
699
803
 
700
- return [#{self}];
701
- }
702
- end
703
-
704
- def to_f
705
- %x{
706
- var result = parseFloat(#{self});
804
+ var result = parseFloat(self.replace(/_/g, ''));
707
805
 
708
- return isNaN(result) ? 0 : result;
806
+ if (isNaN(result) || result == Infinity || result == -Infinity) {
807
+ return 0;
808
+ }
809
+ else {
810
+ return result;
811
+ }
709
812
  }
710
813
  end
711
814
 
712
815
  def to_i(base = 10)
713
816
  %x{
714
- var result = parseInt(#{self}, base);
817
+ var result = parseInt(self, base);
715
818
 
716
819
  if (isNaN(result)) {
717
820
  return 0;
@@ -723,7 +826,7 @@ class String
723
826
 
724
827
  def to_proc
725
828
  %x{
726
- var name = '$' + #{self};
829
+ var name = '$' + self;
727
830
 
728
831
  return function(arg) {
729
832
  var meth = arg[name];
@@ -733,7 +836,7 @@ class String
733
836
  end
734
837
 
735
838
  def to_s
736
- `#{self}.toString()`
839
+ `self.toString()`
737
840
  end
738
841
 
739
842
  alias to_str to_s
@@ -743,7 +846,7 @@ class String
743
846
  def tr(from, to)
744
847
  %x{
745
848
  if (from.length == 0 || from === to) {
746
- return #{self};
849
+ return self;
747
850
  }
748
851
 
749
852
  var subs = {};
@@ -765,12 +868,12 @@ class String
765
868
  var last_from = null;
766
869
  var in_range = false;
767
870
  for (var i = 0; i < from_length; i++) {
768
- var char = from_chars[i];
871
+ var ch = from_chars[i];
769
872
  if (last_from == null) {
770
- last_from = char;
771
- from_chars_expanded.push(char);
873
+ last_from = ch;
874
+ from_chars_expanded.push(ch);
772
875
  }
773
- else if (char === '-') {
876
+ else if (ch === '-') {
774
877
  if (last_from === '-') {
775
878
  from_chars_expanded.push('-');
776
879
  from_chars_expanded.push('-');
@@ -784,16 +887,16 @@ class String
784
887
  }
785
888
  else if (in_range) {
786
889
  var start = last_from.charCodeAt(0) + 1;
787
- var end = char.charCodeAt(0);
890
+ var end = ch.charCodeAt(0);
788
891
  for (var c = start; c < end; c++) {
789
892
  from_chars_expanded.push(String.fromCharCode(c));
790
893
  }
791
- from_chars_expanded.push(char);
894
+ from_chars_expanded.push(ch);
792
895
  in_range = null;
793
896
  last_from = null;
794
897
  }
795
898
  else {
796
- from_chars_expanded.push(char);
899
+ from_chars_expanded.push(ch);
797
900
  }
798
901
  }
799
902
 
@@ -811,12 +914,12 @@ class String
811
914
  var last_to = null;
812
915
  var in_range = false;
813
916
  for (var i = 0; i < to_length; i++) {
814
- var char = to_chars[i];
917
+ var ch = to_chars[i];
815
918
  if (last_from == null) {
816
- last_from = char;
817
- to_chars_expanded.push(char);
919
+ last_from = ch;
920
+ to_chars_expanded.push(ch);
818
921
  }
819
- else if (char === '-') {
922
+ else if (ch === '-') {
820
923
  if (last_to === '-') {
821
924
  to_chars_expanded.push('-');
822
925
  to_chars_expanded.push('-');
@@ -830,16 +933,16 @@ class String
830
933
  }
831
934
  else if (in_range) {
832
935
  var start = last_from.charCodeAt(0) + 1;
833
- var end = char.charCodeAt(0);
936
+ var end = ch.charCodeAt(0);
834
937
  for (var c = start; c < end; c++) {
835
938
  to_chars_expanded.push(String.fromCharCode(c));
836
939
  }
837
- to_chars_expanded.push(char);
940
+ to_chars_expanded.push(ch);
838
941
  in_range = null;
839
942
  last_from = null;
840
943
  }
841
944
  else {
842
- to_chars_expanded.push(char);
945
+ to_chars_expanded.push(ch);
843
946
  }
844
947
  }
845
948
 
@@ -861,14 +964,14 @@ class String
861
964
  }
862
965
 
863
966
  var new_str = ''
864
- for (var i = 0, length = #{self}.length; i < length; i++) {
865
- var char = #{self}.charAt(i);
866
- var sub = subs[char];
967
+ for (var i = 0, length = self.length; i < length; i++) {
968
+ var ch = self.charAt(i);
969
+ var sub = subs[ch];
867
970
  if (inverse) {
868
- new_str += (sub == null ? global_sub : char);
971
+ new_str += (sub == null ? global_sub : ch);
869
972
  }
870
973
  else {
871
- new_str += (sub != null ? sub : char);
974
+ new_str += (sub != null ? sub : ch);
872
975
  }
873
976
  }
874
977
  return new_str;
@@ -878,7 +981,7 @@ class String
878
981
  def tr_s(from, to)
879
982
  %x{
880
983
  if (from.length == 0) {
881
- return #{self};
984
+ return self;
882
985
  }
883
986
 
884
987
  var subs = {};
@@ -900,12 +1003,12 @@ class String
900
1003
  var last_from = null;
901
1004
  var in_range = false;
902
1005
  for (var i = 0; i < from_length; i++) {
903
- var char = from_chars[i];
1006
+ var ch = from_chars[i];
904
1007
  if (last_from == null) {
905
- last_from = char;
906
- from_chars_expanded.push(char);
1008
+ last_from = ch;
1009
+ from_chars_expanded.push(ch);
907
1010
  }
908
- else if (char === '-') {
1011
+ else if (ch === '-') {
909
1012
  if (last_from === '-') {
910
1013
  from_chars_expanded.push('-');
911
1014
  from_chars_expanded.push('-');
@@ -919,16 +1022,16 @@ class String
919
1022
  }
920
1023
  else if (in_range) {
921
1024
  var start = last_from.charCodeAt(0) + 1;
922
- var end = char.charCodeAt(0);
1025
+ var end = ch.charCodeAt(0);
923
1026
  for (var c = start; c < end; c++) {
924
1027
  from_chars_expanded.push(String.fromCharCode(c));
925
1028
  }
926
- from_chars_expanded.push(char);
1029
+ from_chars_expanded.push(ch);
927
1030
  in_range = null;
928
1031
  last_from = null;
929
1032
  }
930
1033
  else {
931
- from_chars_expanded.push(char);
1034
+ from_chars_expanded.push(ch);
932
1035
  }
933
1036
  }
934
1037
 
@@ -946,12 +1049,12 @@ class String
946
1049
  var last_to = null;
947
1050
  var in_range = false;
948
1051
  for (var i = 0; i < to_length; i++) {
949
- var char = to_chars[i];
1052
+ var ch = to_chars[i];
950
1053
  if (last_from == null) {
951
- last_from = char;
952
- to_chars_expanded.push(char);
1054
+ last_from = ch;
1055
+ to_chars_expanded.push(ch);
953
1056
  }
954
- else if (char === '-') {
1057
+ else if (ch === '-') {
955
1058
  if (last_to === '-') {
956
1059
  to_chars_expanded.push('-');
957
1060
  to_chars_expanded.push('-');
@@ -965,16 +1068,16 @@ class String
965
1068
  }
966
1069
  else if (in_range) {
967
1070
  var start = last_from.charCodeAt(0) + 1;
968
- var end = char.charCodeAt(0);
1071
+ var end = ch.charCodeAt(0);
969
1072
  for (var c = start; c < end; c++) {
970
1073
  to_chars_expanded.push(String.fromCharCode(c));
971
1074
  }
972
- to_chars_expanded.push(char);
1075
+ to_chars_expanded.push(ch);
973
1076
  in_range = null;
974
1077
  last_from = null;
975
1078
  }
976
1079
  else {
977
- to_chars_expanded.push(char);
1080
+ to_chars_expanded.push(ch);
978
1081
  }
979
1082
  }
980
1083
 
@@ -996,9 +1099,9 @@ class String
996
1099
  }
997
1100
  var new_str = ''
998
1101
  var last_substitute = null
999
- for (var i = 0, length = #{self}.length; i < length; i++) {
1000
- var char = #{self}.charAt(i);
1001
- var sub = subs[char]
1102
+ for (var i = 0, length = self.length; i < length; i++) {
1103
+ var ch = self.charAt(i);
1104
+ var sub = subs[ch]
1002
1105
  if (inverse) {
1003
1106
  if (sub == null) {
1004
1107
  if (last_substitute == null) {
@@ -1007,7 +1110,7 @@ class String
1007
1110
  }
1008
1111
  }
1009
1112
  else {
1010
- new_str += char;
1113
+ new_str += ch;
1011
1114
  last_substitute = null;
1012
1115
  }
1013
1116
  }
@@ -1019,7 +1122,7 @@ class String
1019
1122
  }
1020
1123
  }
1021
1124
  else {
1022
- new_str += char;
1125
+ new_str += ch;
1023
1126
  last_substitute = null;
1024
1127
  }
1025
1128
  }