opal 0.3.16 → 0.3.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (251) hide show
  1. data/.gitignore +2 -0
  2. data/CHANGELOG.md +12 -0
  3. data/Gemfile +8 -7
  4. data/README.md +21 -13
  5. data/Rakefile +64 -78
  6. data/bin/opal +18 -29
  7. data/core/alpha.rb +2 -9
  8. data/core/array.rb +106 -50
  9. data/core/basic_object.rb +10 -8
  10. data/core/boolean.rb +2 -0
  11. data/core/class.rb +25 -13
  12. data/core/comparable.rb +6 -6
  13. data/core/enumerable.rb +90 -94
  14. data/core/enumerator.rb +3 -3
  15. data/core/hash.rb +86 -46
  16. data/core/kernel.rb +55 -39
  17. data/core/load_order +2 -5
  18. data/core/match_data.rb +1 -1
  19. data/core/module.rb +45 -20
  20. data/core/nil_class.rb +6 -2
  21. data/core/numeric.rb +20 -10
  22. data/core/proc.rb +2 -2
  23. data/core/range.rb +72 -13
  24. data/core/regexp.rb +5 -3
  25. data/core/runtime.js +228 -287
  26. data/core/string.rb +345 -37
  27. data/core/top_self.rb +1 -1
  28. data/lib/opal.rb +13 -91
  29. data/lib/opal/builder.rb +47 -120
  30. data/lib/opal/builder_task.rb +74 -0
  31. data/lib/opal/{parser/grammar.rb → grammar.rb} +1094 -1083
  32. data/lib/opal/{parser/grammar.y → grammar.y} +7 -0
  33. data/lib/opal/{parser/lexer.rb → lexer.rb} +32 -11
  34. data/lib/opal/{parser/parser.rb → parser.rb} +232 -238
  35. data/lib/opal/{parser/scope.rb → scope.rb} +72 -9
  36. data/lib/opal/version.rb +2 -3
  37. data/opal.gemspec +1 -2
  38. data/{core_spec → spec}/core/array/allocate_spec.rb +1 -3
  39. data/{core_spec → spec}/core/array/append_spec.rb +1 -4
  40. data/{core_spec → spec}/core/array/assoc_spec.rb +1 -4
  41. data/{core_spec → spec}/core/array/at_spec.rb +1 -3
  42. data/{core_spec → spec}/core/array/clear_spec.rb +1 -3
  43. data/spec/core/array/clone_spec.rb +15 -0
  44. data/{core_spec/core/array/shared/collect.rb → spec/core/array/collect_spec.rb} +1 -1
  45. data/{core_spec → spec}/core/array/compact_spec.rb +1 -3
  46. data/{core_spec → spec}/core/array/concat_spec.rb +1 -3
  47. data/{core_spec → spec}/core/array/constructor_spec.rb +9 -3
  48. data/{core_spec → spec}/core/array/count_spec.rb +1 -3
  49. data/{core_spec → spec}/core/array/delete_at_spec.rb +1 -4
  50. data/{core_spec → spec}/core/array/delete_if_spec.rb +1 -4
  51. data/{core_spec → spec}/core/array/delete_spec.rb +1 -4
  52. data/{core_spec → spec}/core/array/each_index_spec.rb +1 -4
  53. data/{core_spec → spec}/core/array/each_spec.rb +1 -4
  54. data/{core_spec → spec}/core/array/element_reference_spec.rb +74 -4
  55. data/{core_spec → spec}/core/array/empty_spec.rb +1 -4
  56. data/{core_spec/core/array/shared/eql.rb → spec/core/array/eql_spec.rb} +1 -1
  57. data/{core_spec → spec}/core/array/fetch_spec.rb +1 -4
  58. data/{core_spec → spec}/core/array/first_spec.rb +1 -3
  59. data/{core_spec → spec}/core/array/flatten_spec.rb +1 -3
  60. data/{core_spec → spec}/core/array/include_spec.rb +1 -3
  61. data/{core_spec → spec}/core/array/insert_spec.rb +1 -4
  62. data/{core_spec → spec}/core/array/last_spec.rb +1 -4
  63. data/{core_spec/core/array/shared/length.rb → spec/core/array/length_spec.rb} +1 -1
  64. data/spec/core/array/map_spec.rb +53 -0
  65. data/{core_spec → spec}/core/array/plus_spec.rb +1 -4
  66. data/{core_spec → spec}/core/array/pop_spec.rb +1 -4
  67. data/{core_spec → spec}/core/array/push_spec.rb +1 -4
  68. data/{core_spec → spec}/core/array/rassoc_spec.rb +1 -4
  69. data/{core_spec → spec}/core/array/reject_spec.rb +1 -4
  70. data/{core_spec/core/array/shared/replace.rb → spec/core/array/replace_spec.rb} +1 -1
  71. data/{core_spec → spec}/core/array/reverse_each_spec.rb +1 -4
  72. data/{core_spec → spec}/core/array/reverse_spec.rb +1 -4
  73. data/spec/core/array/size_spec.rb +6 -0
  74. data/spec/core/array/to_ary_spec.rb +6 -0
  75. data/spec/core/array/uniq_spec.rb +22 -0
  76. data/spec/core/array/zip_spec.rb +20 -0
  77. data/{core_spec → spec}/core/class/new_spec.rb +1 -4
  78. data/{core_spec → spec}/core/enumerable/all_spec.rb +1 -4
  79. data/{core_spec → spec}/core/enumerable/any_spec.rb +1 -4
  80. data/{core_spec/core/enumerable/shared/collect.rb → spec/core/enumerable/collect_spec.rb} +1 -1
  81. data/{core_spec → spec}/core/enumerable/count_spec.rb +2 -5
  82. data/{core_spec → spec}/core/enumerable/fixtures/classes.rb +1 -2
  83. data/{core_spec → spec}/core/false/and_spec.rb +1 -3
  84. data/{core_spec → spec}/core/false/inspect_spec.rb +1 -3
  85. data/{core_spec → spec}/core/false/or_spec.rb +1 -3
  86. data/{core_spec → spec}/core/false/to_s_spec.rb +1 -3
  87. data/{core_spec → spec}/core/false/xor_spec.rb +1 -3
  88. data/{core_spec → spec}/core/hash/allocate_spec.rb +1 -3
  89. data/spec/core/hash/assoc_spec.rb +25 -0
  90. data/{core_spec → spec}/core/hash/clear_spec.rb +1 -3
  91. data/{core_spec → spec}/core/hash/clone_spec.rb +1 -3
  92. data/{core_spec → spec}/core/hash/default_spec.rb +1 -3
  93. data/{core_spec → spec}/core/hash/delete_if_spec.rb +1 -3
  94. data/{core_spec → spec}/core/hash/element_reference_spec.rb +1 -3
  95. data/{core_spec → spec}/core/hash/element_set_spec.rb +1 -3
  96. data/spec/core/hash/merge_spec.rb +37 -0
  97. data/{core_spec → spec}/core/hash/new_spec.rb +1 -3
  98. data/{core_spec → spec}/core/matchdata/to_a_spec.rb +1 -3
  99. data/{core_spec → spec}/core/nil/and_spec.rb +1 -4
  100. data/{core_spec → spec}/core/nil/inspect_spec.rb +1 -4
  101. data/{core_spec → spec}/core/nil/nil_spec.rb +1 -4
  102. data/{core_spec → spec}/core/nil/or_spec.rb +1 -4
  103. data/{core_spec → spec}/core/nil/to_a_spec.rb +1 -4
  104. data/{core_spec → spec}/core/nil/to_f_spec.rb +1 -4
  105. data/{core_spec → spec}/core/nil/to_i_spec.rb +1 -4
  106. data/{core_spec → spec}/core/nil/to_s_spec.rb +1 -4
  107. data/{core_spec → spec}/core/nil/xor_spec.rb +1 -4
  108. data/{core_spec → spec}/core/numeric/equal_value_spec.rb +1 -3
  109. data/{core_spec → spec}/core/regexp/match_spec.rb +10 -3
  110. data/{core_spec → spec}/core/symbol/to_proc_spec.rb +1 -3
  111. data/{core_spec → spec}/core/true/and_spec.rb +1 -3
  112. data/{core_spec → spec}/core/true/inspect_spec.rb +1 -3
  113. data/{core_spec → spec}/core/true/or_spec.rb +1 -3
  114. data/{core_spec → spec}/core/true/to_s_spec.rb +1 -3
  115. data/{core_spec → spec}/core/true/xor_spec.rb +1 -3
  116. data/spec/index.html +11 -0
  117. data/{core_spec → spec}/language/alias_spec.rb +1 -3
  118. data/{core_spec → spec}/language/and_spec.rb +1 -4
  119. data/{core_spec → spec}/language/array_spec.rb +1 -4
  120. data/{core_spec → spec}/language/block_spec.rb +20 -3
  121. data/{core_spec → spec}/language/break_spec.rb +40 -3
  122. data/{core_spec → spec}/language/case_spec.rb +1 -4
  123. data/{core_spec → spec}/language/defined_spec.rb +9 -3
  124. data/{core_spec → spec}/language/ensure_spec.rb +38 -3
  125. data/{core_spec → spec}/language/hash_spec.rb +1 -3
  126. data/{core_spec → spec}/language/if_spec.rb +1 -4
  127. data/{core_spec → spec}/language/loop_spec.rb +1 -3
  128. data/spec/language/metaclass_spec.rb +13 -0
  129. data/{core_spec → spec}/language/next_spec.rb +47 -3
  130. data/{core_spec → spec}/language/or_spec.rb +1 -4
  131. data/{core_spec → spec}/language/predefined_spec.rb +1 -3
  132. data/{core_spec/language/regexp/interpolation_spec.rb → spec/language/regexp_spec.rb} +6 -3
  133. data/{core_spec → spec}/language/send_spec.rb +38 -4
  134. data/spec/language/singleton_class_spec.rb +31 -0
  135. data/spec/language/super_spec.rb +188 -0
  136. data/{core_spec → spec}/language/symbol_spec.rb +1 -3
  137. data/{core_spec → spec}/language/undef_spec.rb +1 -3
  138. data/{core_spec → spec}/language/unless_spec.rb +1 -4
  139. data/{core_spec → spec}/language/until_spec.rb +1 -3
  140. data/{core_spec → spec}/language/variables_spec.rb +1 -3
  141. data/{core_spec → spec}/language/while_spec.rb +1 -3
  142. data/{spec → test}/builder/build_source_spec.rb +0 -0
  143. data/{spec → test}/builder/fixtures/build_source/adam.rb +0 -0
  144. data/{spec → test}/builder/fixtures/build_source/bar/a.rb +0 -0
  145. data/{spec → test}/builder/fixtures/build_source/bar/wow/b.rb +0 -0
  146. data/{spec → test}/builder/fixtures/build_source/bar/wow/cow/c.rb +0 -0
  147. data/{spec → test}/builder/fixtures/build_source/beynon.rb +0 -0
  148. data/{spec → test}/builder/fixtures/build_source/charles.js +0 -0
  149. data/{spec → test}/builder/fixtures/build_source/foo/a.rb +0 -0
  150. data/{spec → test}/builder/fixtures/build_source/foo/b.rb +0 -0
  151. data/{spec → test}/builder/fixtures/build_source/foo/x.js +0 -0
  152. data/{spec → test}/builder/fixtures/build_source/foo/y.js +0 -0
  153. data/{spec → test}/grammar/alias_spec.rb +0 -0
  154. data/{spec → test}/grammar/and_spec.rb +0 -0
  155. data/{spec → test}/grammar/array_spec.rb +0 -0
  156. data/{spec → test}/grammar/attrasgn_spec.rb +0 -0
  157. data/{spec → test}/grammar/begin_spec.rb +0 -0
  158. data/{spec → test}/grammar/block_spec.rb +0 -0
  159. data/{spec → test}/grammar/break_spec.rb +0 -0
  160. data/{spec → test}/grammar/call_spec.rb +0 -0
  161. data/{spec → test}/grammar/class_spec.rb +0 -0
  162. data/{spec → test}/grammar/const_spec.rb +0 -0
  163. data/{spec → test}/grammar/cvar_spec.rb +0 -0
  164. data/{spec → test}/grammar/def_spec.rb +0 -0
  165. data/{spec → test}/grammar/false_spec.rb +0 -0
  166. data/{spec → test}/grammar/file_spec.rb +0 -0
  167. data/{spec → test}/grammar/gvar_spec.rb +0 -0
  168. data/{spec → test}/grammar/hash_spec.rb +0 -0
  169. data/{spec → test}/grammar/iasgn_spec.rb +0 -0
  170. data/{spec → test}/grammar/if_spec.rb +0 -0
  171. data/{spec → test}/grammar/iter_spec.rb +0 -0
  172. data/{spec → test}/grammar/ivar_spec.rb +0 -0
  173. data/{spec → test}/grammar/lasgn_spec.rb +0 -0
  174. data/{spec → test}/grammar/line_spec.rb +0 -0
  175. data/{spec → test}/grammar/lvar_spec.rb +0 -0
  176. data/{spec → test}/grammar/masgn_spec.rb +0 -0
  177. data/{spec → test}/grammar/module_spec.rb +0 -0
  178. data/{spec → test}/grammar/nil_spec.rb +0 -0
  179. data/{spec → test}/grammar/not_spec.rb +0 -0
  180. data/{spec → test}/grammar/op_asgn1_spec.rb +0 -0
  181. data/{spec → test}/grammar/op_asgn2_spec.rb +0 -0
  182. data/{spec → test}/grammar/or_spec.rb +0 -0
  183. data/{spec → test}/grammar/return_spec.rb +0 -0
  184. data/{spec → test}/grammar/sclass_spec.rb +0 -0
  185. data/{spec → test}/grammar/self_spec.rb +0 -0
  186. data/{spec → test}/grammar/str_spec.rb +0 -0
  187. data/{spec → test}/grammar/super_spec.rb +0 -0
  188. data/{spec → test}/grammar/true_spec.rb +0 -0
  189. data/{spec → test}/grammar/undef_spec.rb +0 -0
  190. data/{spec → test}/grammar/unless_spec.rb +0 -0
  191. data/{spec → test}/grammar/while_spec.rb +0 -0
  192. data/{spec → test}/grammar/xstr_spec.rb +0 -0
  193. data/{spec → test}/grammar/yield_spec.rb +0 -0
  194. data/{spec → test}/spec_helper.rb +0 -0
  195. metadata +330 -264
  196. data/core/debug.js +0 -59
  197. data/core/debug.rb +0 -35
  198. data/core/dir.rb +0 -90
  199. data/core/file.rb +0 -83
  200. data/core/gemlib.rb +0 -30
  201. data/core/io.rb +0 -44
  202. data/core_spec/README.md +0 -34
  203. data/core_spec/core/array/collect_spec.rb +0 -3
  204. data/core_spec/core/array/element_set_spec.rb +0 -7
  205. data/core_spec/core/array/eql_spec.rb +0 -3
  206. data/core_spec/core/array/equal_value_spec.rb +0 -3
  207. data/core_spec/core/array/fixtures/classes.rb +0 -8
  208. data/core_spec/core/array/length_spec.rb +0 -3
  209. data/core_spec/core/array/map_spec.rb +0 -3
  210. data/core_spec/core/array/replace_spec.rb +0 -3
  211. data/core_spec/core/enumerable/collect_spec.rb +0 -3
  212. data/core_spec/core/enumerable/detect_spec.rb +0 -3
  213. data/core_spec/core/enumerable/find_spec.rb +0 -3
  214. data/core_spec/core/enumerable/first_spec.rb +0 -3
  215. data/core_spec/core/enumerable/shared/entries.rb +0 -7
  216. data/core_spec/core/enumerable/shared/find.rb +0 -49
  217. data/core_spec/core/enumerable/shared/take.rb +0 -31
  218. data/core_spec/core/enumerable/to_a_spec.rb +0 -7
  219. data/core_spec/core/hash/assoc_spec.rb +0 -29
  220. data/core_spec/core/object/is_a_spec.rb +0 -2
  221. data/core_spec/core/object/shared/kind_of.rb +0 -0
  222. data/core_spec/core/regexp/shared/match.rb +0 -11
  223. data/core_spec/language/fixtures/block.rb +0 -19
  224. data/core_spec/language/fixtures/break.rb +0 -39
  225. data/core_spec/language/fixtures/defined.rb +0 -9
  226. data/core_spec/language/fixtures/ensure.rb +0 -37
  227. data/core_spec/language/fixtures/next.rb +0 -46
  228. data/core_spec/language/fixtures/send.rb +0 -36
  229. data/core_spec/language/fixtures/super.rb +0 -43
  230. data/core_spec/language/regexp_spec.rb +0 -7
  231. data/core_spec/language/string_spec.rb +0 -4
  232. data/core_spec/language/super_spec.rb +0 -18
  233. data/core_spec/language/versions/hash_1.9.rb +0 -20
  234. data/core_spec/opal/opal/defined_spec.rb +0 -15
  235. data/core_spec/opal/opal/function_spec.rb +0 -11
  236. data/core_spec/opal/opal/native_spec.rb +0 -16
  237. data/core_spec/opal/opal/null_spec.rb +0 -10
  238. data/core_spec/opal/opal/number_spec.rb +0 -11
  239. data/core_spec/opal/opal/object_spec.rb +0 -16
  240. data/core_spec/opal/opal/string_spec.rb +0 -11
  241. data/core_spec/opal/opal/typeof_spec.rb +0 -9
  242. data/core_spec/opal/opal/undefined_spec.rb +0 -10
  243. data/core_spec/opal/true/case_compare_spec.rb +0 -12
  244. data/core_spec/opal/true/class_spec.rb +0 -10
  245. data/core_spec/release_runner.html +0 -17
  246. data/core_spec/runner.html +0 -16
  247. data/core_spec/spec_helper.rb +0 -23
  248. data/lib/opal/context.rb +0 -269
  249. data/lib/opal/dependency_builder.rb +0 -133
  250. data/lib/opal/environment.rb +0 -87
  251. data/lib/opal/parser/sexp.rb +0 -17
data/core/string.rb CHANGED
@@ -1,8 +1,55 @@
1
1
  class String
2
+ include Comparable
3
+
4
+ def self.try_convert(what)
5
+ what.to_str
6
+ rescue
7
+ null
8
+ end
9
+
2
10
  def self.new(str = '')
3
11
  str.to_s
4
12
  end
5
13
 
14
+ def %(data)
15
+ sprintf self, data
16
+ end
17
+
18
+ def *(count)
19
+ %x{
20
+ if (count < 1) {
21
+ return '';
22
+ }
23
+
24
+ var result = '',
25
+ pattern = this.valueOf();
26
+
27
+ while (count > 0) {
28
+ if (count & 1) {
29
+ result += pattern;
30
+ }
31
+
32
+ count >>= 1, pattern += pattern;
33
+ }
34
+
35
+ return result;
36
+ }
37
+ end
38
+
39
+ def +(other)
40
+ `this + other`
41
+ end
42
+
43
+ def <=>(other)
44
+ %x{
45
+ if (typeof other !== 'string') {
46
+ return null;
47
+ }
48
+
49
+ return this > other ? 1 : (this < other ? -1 : 0);
50
+ }
51
+ end
52
+
6
53
  def <(other)
7
54
  `this < other`
8
55
  end
@@ -19,36 +66,26 @@ class String
19
66
  `this >= other`
20
67
  end
21
68
 
22
- def +(other)
23
- `this + other`
24
- end
25
-
26
- def [](index, length)
27
- `this.substr(index, length)`
28
- end
29
-
30
69
  def ==(other)
31
- `this.valueOf() === other.valueOf()`
70
+ `this == other`
32
71
  end
33
72
 
73
+ alias === ==
74
+
34
75
  def =~(other)
35
76
  %x{
36
77
  if (typeof other === 'string') {
37
- raise(RubyTypeError, 'string given');
78
+ throw RubyTypeError.$new(null, 'string given');
38
79
  }
39
80
 
40
81
  return #{other =~ self};
41
82
  }
42
83
  end
43
84
 
44
- def <=>(other)
45
- %x{
46
- if (typeof other !== 'string') {
47
- return nil;
48
- }
49
-
50
- return this > other ? 1 : (this < other ? -1 : 0);
51
- }
85
+ # TODO: implement range based accessors
86
+ # TODO: implement regex based accessors
87
+ def [](index, length = undefined)
88
+ `this.substr(index, length)`
52
89
  end
53
90
 
54
91
  def capitalize
@@ -68,25 +105,99 @@ class String
68
105
  }
69
106
  end
70
107
 
108
+ def chars
109
+ return enum_for :chars unless block_given?
110
+
111
+ %x{
112
+ for (var i = 0, length = this.length; i < length; i++) {
113
+ #{yield `this.charAt(i)`}
114
+ }
115
+ }
116
+ end
117
+
118
+ def chomp(separator = $/)
119
+ if separator == "\n"
120
+ sub(/(\n|\r|\r\n)$/, '')
121
+ else
122
+ sub(/#{Regexp.escape(separator)}$/, '')
123
+ end
124
+ end
125
+
126
+ def chop
127
+ `this.substr(0, this.length - 1)`
128
+ end
129
+
130
+ def chr
131
+ `this.charAt(0)`
132
+ end
133
+
134
+ def count (*sets)
135
+ raise NotImplementedError
136
+ end
137
+
138
+ def crypt
139
+ raise NotImplementedError
140
+ end
141
+
142
+ def delete (*sets)
143
+ raise NotImplementedErrois
144
+ end
145
+
71
146
  def downcase
72
147
  `this.toLowerCase()`
73
148
  end
74
149
 
75
- def end_with?(suffix)
76
- `this.lastIndexOf(suffix) === this.length - suffix.length`
150
+ alias each_char chars
151
+
152
+ def each_line (separator = $/)
153
+ return enum_for :each_line, separator unless block_given?
154
+
155
+ %x{
156
+ var splitted = this.split(separator);
157
+
158
+ for (var i = 0, length = splitted.length; i < length; i++) {
159
+ #{yield `splitted[i] + separator`}
160
+ }
161
+ }
77
162
  end
78
163
 
79
164
  def empty?
80
165
  `this.length === 0`
81
166
  end
82
167
 
168
+ def end_with?(*suffixes)
169
+ %x{
170
+ for (var i = 0, length = suffixes.length; i < length; i++) {
171
+ var suffix = suffixes[i];
172
+
173
+ if (this.lastIndexOf(suffix) === this.length - suffix.length) {
174
+ return true;
175
+ }
176
+ }
177
+
178
+ return false;
179
+ }
180
+ end
181
+
182
+ alias eql? ==
183
+
184
+ def getbyte(index)
185
+ `this.charCodeAt(index)`
186
+ end
187
+
83
188
  def gsub(pattern, replace = undefined, &block)
189
+ return enum_for :gsub, pattern, replace if !block && `pattern === undefined`
190
+
191
+ if pattern.is_a?(String)
192
+ pattern = /#{Regexp.escape(pattern)}/
193
+ end
194
+
84
195
  %x{
85
- var re = pattern.toString();
86
- re = re.substr(1, re.lastIndexOf('/') - 1);
87
- re = new RegExp(re, 'g');
196
+ var pattern = pattern.toString(),
197
+ options = pattern.substr(pattern.lastIndexOf('/') + 1) + 'g',
198
+ regexp = pattern.substr(1, pattern.lastIndexOf('/') - 1);
88
199
 
89
- return #{sub re, replace, &block};
200
+ return #{sub `new RegExp(regexp, options)`, replace, &block};
90
201
  }
91
202
  end
92
203
 
@@ -94,14 +205,48 @@ class String
94
205
  `this.toString()`
95
206
  end
96
207
 
208
+ def hex
209
+ to_i 16
210
+ end
211
+
97
212
  def include?(other)
98
213
  `this.indexOf(other) !== -1`
99
214
  end
100
215
 
101
- def index(substr)
216
+ def index(what, offset = undefined)
217
+ unless String === what || Regexp === what
218
+ raise TypeError, "type mismatch: #{what.class} given"
219
+ end
220
+
102
221
  %x{
103
- var result = this.indexOf(substr);
104
- return result === -1 ? nil : result
222
+ var result = -1;
223
+
224
+ if (offset !== undefined) {
225
+ if (offset < 0) {
226
+ offset = this.length - offset;
227
+ }
228
+
229
+ if (#{what.is_a?(Regexp)}) {
230
+ result = #{what =~ `this.substr(offset)` || -1}
231
+ }
232
+ else {
233
+ result = this.substr(offset).indexOf(substr);
234
+ }
235
+
236
+ if (result !== -1) {
237
+ result += offset;
238
+ }
239
+ }
240
+ else {
241
+ if (#{what.is_a?(Regexp)}) {
242
+ result = #{(what =~ self) || -1}
243
+ }
244
+ else {
245
+ result = this.indexOf(substr);
246
+ }
247
+ }
248
+
249
+ return result === -1 ? null : result;
105
250
  }
106
251
  end
107
252
 
@@ -133,57 +278,190 @@ class String
133
278
  self
134
279
  end
135
280
 
281
+ alias lines each_line
282
+
136
283
  def length
137
284
  `this.length`
138
285
  end
139
286
 
287
+ def ljust(integer, padstr = ' ')
288
+ raise NotImplementedError
289
+ end
290
+
140
291
  def lstrip
141
292
  `this.replace(/^\s*/, '')`
142
293
  end
143
294
 
295
+ def match(pattern, pos = undefined, &block)
296
+ (pattern.is_a?(Regexp) ? pattern : /#{Regexp.escape(pattern)}/).match(self, pos, &block)
297
+ end
298
+
144
299
  def next
145
- `String.fromCharCode(this.charCodeAt(0))`
300
+ `String.fromCharCode(this.charCodeAt(0) + 1)`
301
+ end
302
+
303
+ def oct
304
+ to_i 8
305
+ end
306
+
307
+ def ord
308
+ `this.charCodeAt(0)`
309
+ end
310
+
311
+ def partition(what)
312
+ %x{
313
+ var result = this.split(what);
314
+
315
+ return [result[0], what.toString(), result.slice(1).join(what.toString())];
316
+ }
146
317
  end
147
318
 
148
319
  def reverse
149
320
  `this.split('').reverse().join('')`
150
321
  end
151
322
 
152
- def split(split, limit = undefined)
153
- `this.split(split, limit)`
323
+ def rpartition(what)
324
+ raise NotImplementedError
325
+ end
326
+
327
+ def rstrip
328
+ `this.replace(/\s*$/, '')`
329
+ end
330
+
331
+ def scan(pattern)
332
+ if pattern.is_a?(String)
333
+ pattern = /#{Regexp.escape(pattern)}/
334
+ end
335
+
336
+ result = []
337
+ original = pattern
338
+
339
+ %x{
340
+ var pattern = pattern.toString(),
341
+ options = pattern.substr(pattern.lastIndexOf('/') + 1) + 'g',
342
+ regexp = pattern.substr(1, pattern.lastIndexOf('/') - 1);
343
+
344
+ var matches = this.match(pattern);
345
+
346
+ for (var i = 0, length = matches.length; i < length; i++) {
347
+ var current = matches[i].match(/^\\(|[^\\\\]\\(/) ? matches[i] : matches[i].match(original);
348
+
349
+ if (#{block_given?}) {
350
+ #{yield current};
351
+ }
352
+ else {
353
+ result.push(current);
354
+ }
355
+ }
356
+ }
357
+
358
+ block_given? ? self : result
359
+ end
360
+
361
+ alias size length
362
+
363
+ alias slice []
364
+
365
+ def split(pattern = $; || ' ', limit = undefined)
366
+ `this.split(pattern === ' ' ? strip : this, limit)`
367
+ end
368
+
369
+ def squeeze(*sets)
370
+ raise NotImplementedError
154
371
  end
155
372
 
156
- def start_with?(prefix)
157
- `this.indexOf(prefix) === 0`
373
+ def start_with?(*prefixes)
374
+ %x{
375
+ for (var i = 0, length = prefixes.length; i < length; i++) {
376
+ if (this.indexOf(prefixes[i]) === 0) {
377
+ return true;
378
+ }
379
+ }
380
+
381
+ return false;
382
+ }
383
+ end
384
+
385
+ def strip
386
+ lstrip.rstrip
158
387
  end
159
388
 
160
389
  def sub(pattern, replace = undefined, &block)
161
390
  %x{
162
- if (block !== nil) {
391
+ if (block !== null) {
163
392
  return this.replace(pattern, function(str) {
164
- return $yield.call($context, str);
393
+ $opal.match_data = arguments
394
+
395
+ return $yielder.call($context, null, str);
165
396
  });
166
397
  }
398
+ else if (#{Object === replace}) {
399
+ if (#{replace.is_a?(Hash)}) {
400
+ return this.replace(pattern, function(str) {
401
+ var value = #{replace[str]};
402
+
403
+ return (value === null) ? undefined : #{value.to_s};
404
+ });
405
+ }
406
+ else {
407
+ replace = #{String.try_convert(replace)};
408
+
409
+ if (replace === null) {
410
+ #{raise TypeError, "can't convert #{replace.class} into String"};
411
+ }
412
+
413
+ return this.replace(pattern, replace);
414
+ }
415
+ }
167
416
  else {
168
- return this.replace(pattern, replace);
417
+ return this.replace(pattern, replace.toString());
169
418
  }
170
419
  }
171
420
  end
172
421
 
173
422
  alias succ next
174
423
 
424
+ def sum(n = 16)
425
+ %x{
426
+ var result = 0;
427
+
428
+ for (var i = 0, length = this.length; i < length; i++) {
429
+ result += this.charCodeAt(i) % ((1 << n) - 1);
430
+ }
431
+
432
+ return result;
433
+ }
434
+ end
435
+
436
+ def swapcase
437
+ %x{
438
+ return this.replace(/([a-z]+)|([A-Z]+)/g, function($0,$1,$2) {
439
+ return $1 ? $0.toUpperCase() : $0.toLowerCase();
440
+ });
441
+ }
442
+ end
443
+
175
444
  def to_f
176
445
  `parseFloat(this)`
177
446
  end
178
447
 
179
448
  def to_i(base = 10)
180
- `parseInt(this, base)`
449
+ %x{
450
+ var result = parseInt(this, base);
451
+
452
+ if (isNaN(result)) {
453
+ return 0;
454
+ }
455
+
456
+ return result;
457
+ }
181
458
  end
182
459
 
183
460
  def to_proc
184
461
  %x{
185
462
  var self = this;
186
- return function(iter, arg) { return arg['$' + self](); };
463
+
464
+ return function(iter, arg) { return arg[mid_to_jsid(self)](); };
187
465
  }
188
466
  end
189
467
 
@@ -191,11 +469,41 @@ class String
191
469
  `this.toString()`
192
470
  end
193
471
 
472
+ alias to_str to_s
473
+
194
474
  alias to_sym intern
195
475
 
476
+ def tr(from, to)
477
+ raise NotImplementedError
478
+ end
479
+
480
+ def tr_s(from, to)
481
+ raise NotImplementedError
482
+ end
483
+
484
+ def unpack(format)
485
+ raise NotImplementedError
486
+ end
487
+
196
488
  def upcase
197
489
  `this.toUpperCase()`
198
490
  end
491
+
492
+ def upto(other, exclusive = false)
493
+ return enum_for :upto, other, exclusive unless block_given?
494
+
495
+ current = self
496
+
497
+ until current == other
498
+ yield current
499
+
500
+ current = current.next
501
+ end
502
+
503
+ yield current unless exclusive
504
+
505
+ self
506
+ end
199
507
  end
200
508
 
201
509
  Symbol = String