opal 0.3.16 → 0.3.17

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