opal 1.6.1 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (212) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +17 -0
  3. data/CHANGELOG.md +35 -1
  4. data/Gemfile +1 -0
  5. data/HACKING.md +47 -26
  6. data/benchmark/benchmarks +415 -103
  7. data/benchmark/bm_call_overhead.yml +28 -0
  8. data/benchmark/run.rb +61 -40
  9. data/docs/cdp_common.json +3364 -0
  10. data/docs/cdp_common.md +18 -0
  11. data/docs/{headless_chrome.md → headless_browsers.md} +31 -12
  12. data/lib/opal/ast/builder.rb +1 -1
  13. data/lib/opal/builder.rb +6 -1
  14. data/lib/opal/builder_processors.rb +5 -3
  15. data/lib/opal/cache.rb +1 -7
  16. data/lib/opal/cli_options.rb +72 -58
  17. data/lib/opal/cli_runners/chrome.rb +47 -9
  18. data/lib/opal/cli_runners/chrome_cdp_interface.rb +238 -112
  19. data/lib/opal/cli_runners/compiler.rb +146 -13
  20. data/lib/opal/cli_runners/deno.rb +32 -0
  21. data/lib/opal/cli_runners/firefox.rb +350 -0
  22. data/lib/opal/cli_runners/firefox_cdp_interface.rb +212 -0
  23. data/lib/opal/cli_runners/node_modules/.bin/chrome-remote-interface.cmd +17 -0
  24. data/lib/opal/cli_runners/node_modules/.bin/chrome-remote-interface.ps1 +28 -0
  25. data/lib/opal/cli_runners/node_modules/.package-lock.json +41 -0
  26. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/LICENSE +1 -1
  27. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/README.md +322 -182
  28. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/bin/client.js +99 -114
  29. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/chrome-remote-interface.js +1 -11
  30. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/index.js +16 -11
  31. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/api.js +41 -33
  32. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/chrome.js +224 -214
  33. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/devtools.js +71 -191
  34. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/external-request.js +26 -6
  35. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/protocol.json +20788 -9049
  36. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/websocket-wrapper.js +10 -3
  37. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/package.json +59 -123
  38. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/webpack.config.js +25 -32
  39. data/lib/opal/cli_runners/node_modules/commander/History.md +298 -0
  40. data/lib/opal/cli_runners/node_modules/commander/LICENSE +22 -0
  41. data/lib/opal/cli_runners/node_modules/commander/Readme.md +217 -61
  42. data/lib/opal/cli_runners/node_modules/commander/index.js +431 -145
  43. data/lib/opal/cli_runners/node_modules/commander/package.json +16 -79
  44. data/lib/opal/cli_runners/node_modules/ws/README.md +334 -98
  45. data/lib/opal/cli_runners/node_modules/ws/browser.js +8 -0
  46. data/lib/opal/cli_runners/node_modules/ws/index.js +5 -10
  47. data/lib/opal/cli_runners/node_modules/ws/lib/buffer-util.js +129 -0
  48. data/lib/opal/cli_runners/node_modules/ws/lib/constants.js +10 -0
  49. data/lib/opal/cli_runners/node_modules/ws/lib/event-target.js +184 -0
  50. data/lib/opal/cli_runners/node_modules/ws/lib/extension.js +223 -0
  51. data/lib/opal/cli_runners/node_modules/ws/lib/limiter.js +55 -0
  52. data/lib/opal/cli_runners/node_modules/ws/lib/permessage-deflate.js +518 -0
  53. data/lib/opal/cli_runners/node_modules/ws/lib/receiver.js +607 -0
  54. data/lib/opal/cli_runners/node_modules/ws/lib/sender.js +409 -0
  55. data/lib/opal/cli_runners/node_modules/ws/lib/stream.js +180 -0
  56. data/lib/opal/cli_runners/node_modules/ws/lib/validation.js +104 -0
  57. data/lib/opal/cli_runners/node_modules/ws/lib/websocket-server.js +447 -0
  58. data/lib/opal/cli_runners/node_modules/ws/lib/websocket.js +1195 -0
  59. data/lib/opal/cli_runners/node_modules/ws/package.json +40 -106
  60. data/lib/opal/cli_runners/package-lock.json +62 -0
  61. data/lib/opal/cli_runners/package.json +1 -1
  62. data/lib/opal/cli_runners.rb +26 -4
  63. data/lib/opal/nodes/args/prepare_post_args.rb +2 -2
  64. data/lib/opal/nodes/def.rb +8 -8
  65. data/lib/opal/nodes/iter.rb +12 -12
  66. data/lib/opal/nodes/logic.rb +1 -1
  67. data/lib/opal/nodes/masgn.rb +2 -2
  68. data/lib/opal/parser/with_ruby_lexer.rb +1 -1
  69. data/lib/opal/paths.rb +14 -0
  70. data/lib/opal/rewriter.rb +2 -0
  71. data/lib/opal/rewriters/forward_args.rb +52 -4
  72. data/lib/opal/rewriters/targeted_patches.rb +94 -0
  73. data/lib/opal/version.rb +1 -1
  74. data/opal/corelib/basic_object.rb +1 -1
  75. data/opal/corelib/boolean.rb +2 -2
  76. data/opal/corelib/class.rb +11 -0
  77. data/opal/corelib/constants.rb +3 -3
  78. data/opal/corelib/enumerable.rb +4 -0
  79. data/opal/corelib/enumerator.rb +1 -1
  80. data/opal/corelib/hash.rb +2 -2
  81. data/opal/corelib/helpers.rb +1 -1
  82. data/opal/corelib/kernel.rb +3 -3
  83. data/opal/corelib/method.rb +1 -1
  84. data/opal/corelib/module.rb +29 -8
  85. data/opal/corelib/proc.rb +7 -5
  86. data/opal/corelib/runtime.js +141 -78
  87. data/opal/corelib/set.rb +252 -0
  88. data/opal/corelib/string.rb +2 -1
  89. data/opal/corelib/time.rb +2 -2
  90. data/opal/opal.rb +1 -0
  91. data/opal.gemspec +1 -0
  92. data/spec/filters/bugs/array.rb +22 -13
  93. data/spec/filters/bugs/base64.rb +5 -5
  94. data/spec/filters/bugs/basicobject.rb +16 -8
  95. data/spec/filters/bugs/bigdecimal.rb +161 -160
  96. data/spec/filters/bugs/binding.rb +10 -10
  97. data/spec/filters/bugs/class.rb +8 -8
  98. data/spec/filters/bugs/complex.rb +2 -1
  99. data/spec/filters/bugs/date.rb +79 -81
  100. data/spec/filters/bugs/datetime.rb +29 -29
  101. data/spec/filters/bugs/delegate.rb +1 -3
  102. data/spec/filters/bugs/encoding.rb +69 -69
  103. data/spec/filters/bugs/enumerable.rb +22 -20
  104. data/spec/filters/bugs/enumerator.rb +88 -85
  105. data/spec/filters/bugs/exception.rb +46 -40
  106. data/spec/filters/bugs/file.rb +32 -32
  107. data/spec/filters/bugs/float.rb +26 -21
  108. data/spec/filters/bugs/freeze.rb +88 -0
  109. data/spec/filters/bugs/hash.rb +39 -38
  110. data/spec/filters/bugs/integer.rb +57 -44
  111. data/spec/filters/bugs/io.rb +1 -1
  112. data/spec/filters/bugs/kernel.rb +349 -269
  113. data/spec/filters/bugs/language.rb +220 -188
  114. data/spec/filters/bugs/main.rb +5 -3
  115. data/spec/filters/bugs/marshal.rb +38 -38
  116. data/spec/filters/bugs/math.rb +2 -1
  117. data/spec/filters/bugs/method.rb +73 -62
  118. data/spec/filters/bugs/module.rb +163 -143
  119. data/spec/filters/bugs/numeric.rb +6 -6
  120. data/spec/filters/bugs/objectspace.rb +16 -16
  121. data/spec/filters/bugs/openstruct.rb +1 -1
  122. data/spec/filters/bugs/pack_unpack.rb +51 -51
  123. data/spec/filters/bugs/pathname.rb +7 -7
  124. data/spec/filters/bugs/proc.rb +63 -63
  125. data/spec/filters/bugs/random.rb +7 -6
  126. data/spec/filters/bugs/range.rb +12 -9
  127. data/spec/filters/bugs/rational.rb +8 -7
  128. data/spec/filters/bugs/regexp.rb +49 -48
  129. data/spec/filters/bugs/ruby-32.rb +56 -0
  130. data/spec/filters/bugs/set.rb +30 -30
  131. data/spec/filters/bugs/singleton.rb +4 -4
  132. data/spec/filters/bugs/string.rb +187 -99
  133. data/spec/filters/bugs/stringio.rb +7 -0
  134. data/spec/filters/bugs/stringscanner.rb +68 -68
  135. data/spec/filters/bugs/struct.rb +11 -9
  136. data/spec/filters/bugs/symbol.rb +1 -1
  137. data/spec/filters/bugs/time.rb +78 -63
  138. data/spec/filters/bugs/trace_point.rb +4 -4
  139. data/spec/filters/bugs/unboundmethod.rb +32 -17
  140. data/spec/filters/bugs/warnings.rb +8 -12
  141. data/spec/filters/unsupported/array.rb +24 -107
  142. data/spec/filters/unsupported/basicobject.rb +12 -12
  143. data/spec/filters/unsupported/bignum.rb +27 -52
  144. data/spec/filters/unsupported/class.rb +1 -2
  145. data/spec/filters/unsupported/delegator.rb +3 -3
  146. data/spec/filters/unsupported/enumerable.rb +2 -9
  147. data/spec/filters/unsupported/enumerator.rb +2 -11
  148. data/spec/filters/unsupported/file.rb +1 -1
  149. data/spec/filters/unsupported/float.rb +28 -47
  150. data/spec/filters/unsupported/hash.rb +8 -14
  151. data/spec/filters/unsupported/integer.rb +75 -91
  152. data/spec/filters/unsupported/kernel.rb +17 -35
  153. data/spec/filters/unsupported/language.rb +11 -19
  154. data/spec/filters/unsupported/marshal.rb +22 -41
  155. data/spec/filters/unsupported/matchdata.rb +28 -52
  156. data/spec/filters/unsupported/math.rb +1 -1
  157. data/spec/filters/unsupported/privacy.rb +229 -285
  158. data/spec/filters/unsupported/range.rb +1 -5
  159. data/spec/filters/unsupported/regexp.rb +40 -66
  160. data/spec/filters/unsupported/set.rb +2 -2
  161. data/spec/filters/unsupported/singleton.rb +4 -4
  162. data/spec/filters/unsupported/string.rb +305 -508
  163. data/spec/filters/unsupported/struct.rb +3 -4
  164. data/spec/filters/unsupported/symbol.rb +15 -18
  165. data/spec/filters/unsupported/thread.rb +1 -7
  166. data/spec/filters/unsupported/time.rb +159 -202
  167. data/spec/filters/unsupported/usage_of_files.rb +170 -259
  168. data/spec/lib/builder_spec.rb +4 -4
  169. data/spec/lib/rewriters/forward_args_spec.rb +32 -12
  170. data/spec/mspec-opal/runner.rb +2 -0
  171. data/spec/ruby_specs +4 -0
  172. data/stdlib/deno/base.rb +28 -0
  173. data/stdlib/deno/file.rb +340 -0
  174. data/stdlib/{headless_chrome.rb → headless_browser/base.rb} +1 -1
  175. data/stdlib/headless_browser/file.rb +15 -0
  176. data/stdlib/headless_browser.rb +4 -0
  177. data/stdlib/native.rb +1 -1
  178. data/stdlib/nodejs/file.rb +5 -0
  179. data/stdlib/opal/platform.rb +8 -6
  180. data/stdlib/opal-platform.rb +14 -8
  181. data/stdlib/set.rb +1 -258
  182. data/tasks/benchmarking.rake +62 -19
  183. data/tasks/performance.rake +1 -1
  184. data/tasks/testing.rake +5 -3
  185. data/test/nodejs/test_file.rb +29 -10
  186. data/test/opal/http_server.rb +28 -11
  187. data/test/opal/unsupported_and_bugs.rb +2 -1
  188. metadata +89 -50
  189. data/lib/opal/cli_runners/node_modules/ultron/LICENSE +0 -22
  190. data/lib/opal/cli_runners/node_modules/ultron/index.js +0 -138
  191. data/lib/opal/cli_runners/node_modules/ultron/package.json +0 -112
  192. data/lib/opal/cli_runners/node_modules/ws/SECURITY.md +0 -33
  193. data/lib/opal/cli_runners/node_modules/ws/lib/BufferUtil.fallback.js +0 -56
  194. data/lib/opal/cli_runners/node_modules/ws/lib/BufferUtil.js +0 -15
  195. data/lib/opal/cli_runners/node_modules/ws/lib/ErrorCodes.js +0 -28
  196. data/lib/opal/cli_runners/node_modules/ws/lib/EventTarget.js +0 -158
  197. data/lib/opal/cli_runners/node_modules/ws/lib/Extensions.js +0 -69
  198. data/lib/opal/cli_runners/node_modules/ws/lib/PerMessageDeflate.js +0 -339
  199. data/lib/opal/cli_runners/node_modules/ws/lib/Receiver.js +0 -520
  200. data/lib/opal/cli_runners/node_modules/ws/lib/Sender.js +0 -438
  201. data/lib/opal/cli_runners/node_modules/ws/lib/Validation.fallback.js +0 -9
  202. data/lib/opal/cli_runners/node_modules/ws/lib/Validation.js +0 -17
  203. data/lib/opal/cli_runners/node_modules/ws/lib/WebSocket.js +0 -705
  204. data/lib/opal/cli_runners/node_modules/ws/lib/WebSocketServer.js +0 -336
  205. data/spec/filters/bugs/boolean.rb +0 -3
  206. data/spec/filters/bugs/matrix.rb +0 -3
  207. data/spec/filters/unsupported/fixnum.rb +0 -15
  208. data/spec/filters/unsupported/freeze.rb +0 -102
  209. data/spec/filters/unsupported/pathname.rb +0 -4
  210. data/spec/filters/unsupported/proc.rb +0 -4
  211. data/spec/filters/unsupported/random.rb +0 -5
  212. data/spec/filters/unsupported/taint.rb +0 -162
@@ -77,11 +77,12 @@
77
77
  };
78
78
 
79
79
  // Minify common function calls
80
- var $has_own = Object.hasOwnProperty;
80
+ var $call = Function.prototype.call;
81
81
  var $bind = Function.prototype.bind;
82
+ var $has_own = Object.hasOwn || $call.bind(Object.prototype.hasOwnProperty);
82
83
  var $set_proto = Object.setPrototypeOf;
83
- var $slice = Array.prototype.slice;
84
- var $splice = Array.prototype.splice;
84
+ var $slice = $call.bind(Array.prototype.slice);
85
+ var $splice = $call.bind(Array.prototype.splice);
85
86
 
86
87
  // Nil object id is always 4
87
88
  var nil_id = 4;
@@ -129,6 +130,28 @@
129
130
  }
130
131
  };
131
132
 
133
+ // A helper function for raising things, that gracefully degrades if necessary
134
+ // functionality is not yet loaded.
135
+ function $raise(klass, message) {
136
+ // Raise Exception, so we can know that something wrong is going on.
137
+ if (!klass) klass = Opal.Exception || Error;
138
+
139
+ if (Kernel && Kernel.$raise) {
140
+ if (arguments.length > 2) {
141
+ Kernel.$raise(klass.$new.apply(klass, $slice(arguments, 1)));
142
+ }
143
+ else {
144
+ Kernel.$raise(klass, message);
145
+ }
146
+ }
147
+ else if (!klass.$new) {
148
+ throw new klass(message);
149
+ }
150
+ else {
151
+ throw klass.$new(message);
152
+ }
153
+ }
154
+
132
155
  function $prop(object, name, initialValue) {
133
156
  if (typeof(object) === "string") {
134
157
  // Special case for:
@@ -156,7 +179,6 @@
156
179
 
157
180
  Opal.slice = $slice;
158
181
 
159
-
160
182
  // Helpers
161
183
  // -----
162
184
 
@@ -173,12 +195,12 @@
173
195
 
174
196
  if (coerced && method) {
175
197
  coerced = coerced.$$class;
176
- return Opal.TypeError.$new(
198
+ $raise(Opal.TypeError,
177
199
  "can't convert " + object + " into " + type +
178
200
  " (" + object + "#" + method + " gives " + coerced + ")"
179
201
  )
180
202
  } else {
181
- return Opal.TypeError.$new(
203
+ $raise(Opal.TypeError,
182
204
  "no implicit conversion of " + object + " into " + type
183
205
  )
184
206
  }
@@ -197,13 +219,13 @@
197
219
 
198
220
  // Fast path for the most common situation
199
221
  if (object['$respond_to?'].$$pristine && object.$method_missing.$$pristine) {
200
- body = object['$' + method];
201
- if (body == null || body.$$stub) throw Opal.type_error(object, type);
222
+ body = object[$jsid(method)];
223
+ if (body == null || body.$$stub) Opal.type_error(object, type);
202
224
  return body.apply(object, args);
203
225
  }
204
226
 
205
227
  if (!object['$respond_to?'](method)) {
206
- throw Opal.type_error(object, type);
228
+ Opal.type_error(object, type);
207
229
  }
208
230
 
209
231
  if (args == null) args = [];
@@ -312,7 +334,7 @@
312
334
  ancestors = $ancestors(cref);
313
335
 
314
336
  for (i = 0, ii = ancestors.length; i < ii; i++) {
315
- if (ancestors[i].$$const && $has_own.call(ancestors[i].$$const, name)) {
337
+ if (ancestors[i].$$const && $has_own(ancestors[i].$$const, name)) {
316
338
  return ancestors[i].$$const[name];
317
339
  } else if (ancestors[i].$$autoload && ancestors[i].$$autoload[name]) {
318
340
  return handle_autoload(ancestors[i], name);
@@ -342,7 +364,7 @@
342
364
  if (cref === '::') cref = _Object;
343
365
 
344
366
  if (!cref.$$is_module && !cref.$$is_class) {
345
- throw new Opal.TypeError(cref.toString() + " is not a class/module");
367
+ $raise(Opal.TypeError, cref.toString() + " is not a class/module");
346
368
  }
347
369
 
348
370
  result = const_get_name(cref, name);
@@ -367,7 +389,7 @@
367
389
  if (cref === '::') cref = _Object;
368
390
 
369
391
  if (!cref.$$is_module && !cref.$$is_class) {
370
- throw new Opal.TypeError(cref.toString() + " is not a class/module");
392
+ $raise(Opal.TypeError, cref.toString() + " is not a class/module");
371
393
  }
372
394
 
373
395
  if ((cache = cref.$$const_cache) == null) {
@@ -418,6 +440,8 @@
418
440
  // Register the constant on a cref and opportunistically set the name of
419
441
  // unnamed classes/modules.
420
442
  function $const_set(cref, name, value) {
443
+ var new_const = true;
444
+
421
445
  if (cref == null || cref === '::') cref = _Object;
422
446
 
423
447
  if (value.$$is_a_module) {
@@ -426,6 +450,11 @@
426
450
  }
427
451
 
428
452
  cref.$$const = (cref.$$const || Object.create(null));
453
+
454
+ if (name in cref.$$const || ("$$autoload" in cref && name in cref.$$autoload)) {
455
+ new_const = false;
456
+ }
457
+
429
458
  cref.$$const[name] = value;
430
459
 
431
460
  // Add a short helper to navigate constants manually.
@@ -441,6 +470,10 @@
441
470
  // Name new class directly onto current scope (Opal.Foo.Baz = klass)
442
471
  $prop(cref, name, value);
443
472
 
473
+ if (new_const && cref.$const_added && !cref.$const_added.$$pristine) {
474
+ cref.$const_added(name);
475
+ }
476
+
444
477
  return value;
445
478
  };
446
479
 
@@ -490,7 +523,7 @@
490
523
  return nil;
491
524
  }
492
525
 
493
- throw Opal.NameError.$new("constant "+cref+"::"+cref.$name()+" not defined");
526
+ $raise(Opal.NameError, "constant "+cref+"::"+cref.$name()+" not defined");
494
527
  };
495
528
 
496
529
  // Generates a function that is a curried const_get_relative.
@@ -540,7 +573,7 @@
540
573
  // Inheritance from bridged classes requires
541
574
  // calling original JS constructors
542
575
  klass = function() {
543
- var args = $slice.call(arguments),
576
+ var args = $slice(arguments),
544
577
  self = new ($bind.apply(superclass.$$constructor, [null].concat(args)))();
545
578
 
546
579
  // and replacing a __proto__ manually
@@ -622,7 +655,7 @@
622
655
  if (klass) {
623
656
  // Make sure the existing constant is a class, or raise error
624
657
  if (!klass.$$is_class) {
625
- throw Opal.TypeError.$new(name + " is not a class");
658
+ $raise(Opal.TypeError, name + " is not a class");
626
659
  }
627
660
 
628
661
  return klass;
@@ -631,7 +664,7 @@
631
664
 
632
665
  function ensureSuperclassMatch(klass, superclass) {
633
666
  if (klass.$$super !== superclass) {
634
- throw Opal.TypeError.$new("superclass mismatch for class " + klass.$$name);
667
+ $raise(Opal.TypeError, "superclass mismatch for class " + klass.$$name);
635
668
  }
636
669
  }
637
670
 
@@ -656,7 +689,7 @@
656
689
  bridged = superclass;
657
690
  superclass = _Object;
658
691
  } else {
659
- throw Opal.TypeError.$new("superclass must be a Class (" + (
692
+ $raise(Opal.TypeError, "superclass must be a Class (" + (
660
693
  (superclass.constructor && (superclass.constructor.name || superclass.constructor.$$name)) ||
661
694
  typeof(superclass)
662
695
  ) + " given)");
@@ -748,7 +781,7 @@
748
781
 
749
782
  if (module) {
750
783
  if (!module.$$is_module && module !== _Object) {
751
- throw Opal.TypeError.$new(name + " is not a module");
784
+ $raise(Opal.TypeError, name + " is not a module");
752
785
  }
753
786
  }
754
787
 
@@ -999,7 +1032,7 @@
999
1032
  for (i = length - 2; i >= 0; i--) {
1000
1033
  var ancestor = ancestors[i];
1001
1034
 
1002
- if ($has_own.call(ancestor.$$cvars, name)) {
1035
+ if ($has_own(ancestor.$$cvars, name)) {
1003
1036
  ancestor.$$cvars[name] = value;
1004
1037
  return value;
1005
1038
  }
@@ -1015,7 +1048,7 @@
1015
1048
  // @param module [Module]
1016
1049
  // @param name [String]
1017
1050
  Opal.class_variable_get = function(module, name, tolerant) {
1018
- if ($has_own.call(module.$$cvars, name))
1051
+ if ($has_own(module.$$cvars, name))
1019
1052
  return module.$$cvars[name];
1020
1053
 
1021
1054
  var ancestors = $ancestors(module),
@@ -1024,13 +1057,13 @@
1024
1057
  for (i = 0; i < length; i++) {
1025
1058
  var ancestor = ancestors[i];
1026
1059
 
1027
- if ($has_own.call(ancestor.$$cvars, name)) {
1060
+ if ($has_own(ancestor.$$cvars, name)) {
1028
1061
  return ancestor.$$cvars[name];
1029
1062
  }
1030
1063
  }
1031
1064
 
1032
1065
  if (!tolerant)
1033
- throw Opal.NameError.$new('uninitialized class variable '+name+' in '+module.$name());
1066
+ $raise(Opal.NameError, 'uninitialized class variable '+name+' in '+module.$name());
1034
1067
 
1035
1068
  return nil;
1036
1069
  }
@@ -1102,7 +1135,7 @@
1102
1135
  var iclasses = [];
1103
1136
 
1104
1137
  if (module_ancestors.indexOf(includer) !== -1) {
1105
- throw Opal.ArgumentError.$new('cyclic include detected');
1138
+ $raise(Opal.ArgumentError, 'cyclic include detected');
1106
1139
  }
1107
1140
 
1108
1141
  for (var i = 0, length = module_ancestors.length; i < length; i++) {
@@ -1207,7 +1240,7 @@
1207
1240
  var iclasses = [];
1208
1241
 
1209
1242
  if (module_ancestors.indexOf(prepender) !== -1) {
1210
- throw Opal.ArgumentError.$new('cyclic prepend detected');
1243
+ $raise(Opal.ArgumentError, 'cyclic prepend detected');
1211
1244
  }
1212
1245
 
1213
1246
  for (var i = 0, length = module_ancestors.length; i < length; i++) {
@@ -1263,7 +1296,7 @@
1263
1296
  end_chain_on = Object.getPrototypeOf(end_chain_on);
1264
1297
  }
1265
1298
  } else {
1266
- throw Opal.RuntimeError.$new("Prepending a module multiple times is not supported");
1299
+ $raise(Opal.RuntimeError, "Prepending a module multiple times is not supported");
1267
1300
  }
1268
1301
 
1269
1302
  $set_proto(start_chain_after, chain.first);
@@ -1360,7 +1393,7 @@
1360
1393
  //
1361
1394
  Opal.bridge = function(native_klass, klass) {
1362
1395
  if (native_klass.hasOwnProperty('$$bridge')) {
1363
- throw Opal.ArgumentError.$new("already bridged");
1396
+ $raise(Opal.ArgumentError, "already bridged");
1364
1397
  }
1365
1398
 
1366
1399
  // constructor is a JS function with a prototype chain like:
@@ -1478,7 +1511,7 @@
1478
1511
  stubs = stubs.split(',');
1479
1512
 
1480
1513
  for (var i = 0, length = stubs.length; i < length; i++) {
1481
- stub = '$'+stubs[i], existing_method = proto[stub];
1514
+ stub = $jsid(stubs[i]), existing_method = proto[stub];
1482
1515
 
1483
1516
  if (existing_method == null || existing_method.$$stub) {
1484
1517
  Opal.add_stub_for(proto, stub);
@@ -1543,7 +1576,7 @@
1543
1576
  }
1544
1577
  inspect += meth;
1545
1578
 
1546
- throw Opal.ArgumentError.$new('[' + inspect + '] wrong number of arguments (given ' + actual + ', expected ' + expected + ')');
1579
+ $raise(Opal.ArgumentError, '[' + inspect + '] wrong number of arguments (given ' + actual + ', expected ' + expected + ')');
1547
1580
  };
1548
1581
 
1549
1582
  // Arity count error dispatcher for blocks
@@ -1555,7 +1588,7 @@
1555
1588
  Opal.block_ac = function(actual, expected, context) {
1556
1589
  var inspect = "`block in " + context + "'";
1557
1590
 
1558
- throw Opal.ArgumentError.$new(inspect + ': wrong number of arguments (given ' + actual + ', expected ' + expected + ')');
1591
+ $raise(Opal.ArgumentError, inspect + ': wrong number of arguments (given ' + actual + ', expected ' + expected + ')');
1559
1592
  };
1560
1593
 
1561
1594
  function get_ancestors(obj) {
@@ -1568,7 +1601,7 @@
1568
1601
 
1569
1602
  // Super dispatcher
1570
1603
  Opal.find_super = function(obj, mid, current_func, defcheck, allow_stubs) {
1571
- var jsid = '$' + mid, ancestors, super_method;
1604
+ var jsid = $jsid(mid), ancestors, super_method;
1572
1605
 
1573
1606
  ancestors = get_ancestors(obj);
1574
1607
 
@@ -1590,7 +1623,7 @@
1590
1623
 
1591
1624
  if (!defcheck && super_method && super_method.$$stub && obj.$method_missing.$$pristine) {
1592
1625
  // method_missing hasn't been explicitly defined
1593
- throw Opal.NoMethodError.$new('super: no superclass method `'+mid+"' for "+obj, mid);
1626
+ $raise(Opal.NoMethodError, 'super: no superclass method `'+mid+"' for "+obj, mid);
1594
1627
  }
1595
1628
 
1596
1629
  return (super_method.$$stub && !allow_stubs) ? null : super_method;
@@ -1601,11 +1634,11 @@
1601
1634
  var call_jsid = jsid;
1602
1635
 
1603
1636
  if (!current_func) {
1604
- throw Opal.RuntimeError.$new("super called outside of method");
1637
+ $raise(Opal.RuntimeError, "super called outside of method");
1605
1638
  }
1606
1639
 
1607
1640
  if (implicit && current_func.$$define_meth) {
1608
- throw Opal.RuntimeError.$new(
1641
+ $raise(Opal.RuntimeError,
1609
1642
  "implicit argument passing of super from method defined by define_method() is not supported. " +
1610
1643
  "Specify all arguments explicitly"
1611
1644
  );
@@ -1627,7 +1660,7 @@
1627
1660
  // handles yield calls for 1 yielded arg
1628
1661
  Opal.yield1 = function(block, arg) {
1629
1662
  if (typeof(block) !== "function") {
1630
- throw Opal.LocalJumpError.$new("no block given");
1663
+ $raise(Opal.LocalJumpError, "no block given");
1631
1664
  }
1632
1665
 
1633
1666
  var has_mlhs = block.$$has_top_level_mlhs_arg,
@@ -1648,7 +1681,7 @@
1648
1681
  // handles yield for > 1 yielded arg
1649
1682
  Opal.yieldX = function(block, args) {
1650
1683
  if (typeof(block) !== "function") {
1651
- throw Opal.LocalJumpError.$new("no block given");
1684
+ $raise(Opal.LocalJumpError, "no block given");
1652
1685
  }
1653
1686
 
1654
1687
  if (block.length > 1 && args.length === 1) {
@@ -1714,12 +1747,12 @@
1714
1747
  return hash;
1715
1748
  }
1716
1749
  else {
1717
- throw Opal.TypeError.$new("Can't convert " + value.$$class +
1750
+ $raise(Opal.TypeError, "Can't convert " + value.$$class +
1718
1751
  " to Hash (" + value.$$class + "#to_hash gives " + hash.$$class + ")");
1719
1752
  }
1720
1753
  }
1721
1754
  else {
1722
- throw Opal.TypeError.$new("no implicit conversion of " + value.$$class + " into Hash");
1755
+ $raise(Opal.TypeError, "no implicit conversion of " + value.$$class + " into Hash");
1723
1756
  }
1724
1757
  };
1725
1758
 
@@ -1742,7 +1775,7 @@
1742
1775
  return ary;
1743
1776
  }
1744
1777
  else {
1745
- throw Opal.TypeError.$new("Can't convert " + value.$$class +
1778
+ $raise(Opal.TypeError, "Can't convert " + value.$$class +
1746
1779
  " to Array (" + value.$$class + "#to_ary gives " + ary.$$class + ")");
1747
1780
  }
1748
1781
  }
@@ -1766,7 +1799,7 @@
1766
1799
  return ary;
1767
1800
  }
1768
1801
  else {
1769
- throw Opal.TypeError.$new("Can't convert " + value.$$class +
1802
+ $raise(Opal.TypeError, "Can't convert " + value.$$class +
1770
1803
  " to Array (" + value.$$class + "#to_a gives " + ary.$$class + ")");
1771
1804
  }
1772
1805
  }
@@ -1785,7 +1818,7 @@
1785
1818
  Opal.extract_kwargs = function(parameters) {
1786
1819
  var kwargs = parameters[parameters.length - 1];
1787
1820
  if (kwargs != null && Opal.respond_to(kwargs, '$to_hash', true)) {
1788
- $splice.call(parameters, parameters.length - 1);
1821
+ $splice(parameters, parameters.length - 1);
1789
1822
  return kwargs;
1790
1823
  }
1791
1824
  };
@@ -1826,6 +1859,13 @@
1826
1859
  }
1827
1860
  }
1828
1861
 
1862
+ // Optimization for a costly operation of prepending '$' to method names
1863
+ var jsid_cache = {}
1864
+ function $jsid(name) {
1865
+ return jsid_cache[name] || (jsid_cache[name] = '$' + name);
1866
+ }
1867
+ Opal.jsid = $jsid;
1868
+
1829
1869
  // Calls passed method on a ruby object with arguments and block:
1830
1870
  //
1831
1871
  // Can take a method or a method name.
@@ -1858,9 +1898,9 @@
1858
1898
  body = method;
1859
1899
  method = null;
1860
1900
  } else if (typeof(method) === 'string') {
1861
- body = recv['$'+method];
1901
+ body = recv[$jsid(method)];
1862
1902
  } else {
1863
- throw Opal.NameError.$new("Passed method should be a string or a function");
1903
+ $raise(Opal.NameError, "Passed method should be a string or a function");
1864
1904
  }
1865
1905
 
1866
1906
  return Opal.send2(recv, body, method, args, block, blockopts);
@@ -1905,8 +1945,8 @@
1905
1945
  refine_module = refine_modules[ancestor];
1906
1946
 
1907
1947
  // Does this module define a method we want to call?
1908
- if (typeof refine_module.$$prototype['$'+method] !== 'undefined') {
1909
- body = refine_module.$$prototype['$'+method];
1948
+ if (typeof refine_module.$$prototype[$jsid(method)] !== 'undefined') {
1949
+ body = refine_module.$$prototype[$jsid(method)];
1910
1950
  return Opal.send2(recv, body, method, args, block, blockopts);
1911
1951
  }
1912
1952
  }
@@ -2020,15 +2060,15 @@
2020
2060
  apply_blockopts(body, blockopts);
2021
2061
 
2022
2062
  if (obj.$$is_string || obj.$$is_number) {
2023
- throw Opal.TypeError.$new("can't define singleton");
2063
+ $raise(Opal.TypeError, "can't define singleton");
2024
2064
  }
2025
2065
  return Opal.defn(Opal.get_singleton_class(obj), jsid, body);
2026
2066
  };
2027
2067
 
2028
2068
  // Called from #remove_method.
2029
2069
  Opal.rdef = function(obj, jsid) {
2030
- if (!$has_own.call(obj.$$prototype, jsid)) {
2031
- throw Opal.NameError.$new("method '" + jsid.substr(1) + "' not defined in " + obj.$name());
2070
+ if (!$has_own(obj.$$prototype, jsid)) {
2071
+ $raise(Opal.NameError, "method '" + jsid.substr(1) + "' not defined in " + obj.$name());
2032
2072
  }
2033
2073
 
2034
2074
  delete obj.$$prototype[jsid];
@@ -2048,7 +2088,7 @@
2048
2088
  // Called from #undef_method.
2049
2089
  Opal.udef = function(obj, jsid) {
2050
2090
  if (!obj.$$prototype[jsid] || obj.$$prototype[jsid].$$stub) {
2051
- throw Opal.NameError.$new("method '" + jsid.substr(1) + "' not defined in " + obj.$name());
2091
+ $raise(Opal.NameError, "method '" + jsid.substr(1) + "' not defined in " + obj.$name());
2052
2092
  }
2053
2093
 
2054
2094
  Opal.add_stub_for(obj.$$prototype, jsid);
@@ -2070,8 +2110,8 @@
2070
2110
  }
2071
2111
 
2072
2112
  Opal.alias = function(obj, name, old) {
2073
- var id = '$' + name,
2074
- old_id = '$' + old,
2113
+ var id = $jsid(name),
2114
+ old_id = $jsid(old),
2075
2115
  body,
2076
2116
  alias;
2077
2117
 
@@ -2080,7 +2120,7 @@
2080
2120
  obj = Opal.Object;
2081
2121
  }
2082
2122
 
2083
- body = obj.$$prototype['$' + old];
2123
+ body = obj.$$prototype[old_id];
2084
2124
 
2085
2125
  // When running inside #instance_eval the alias refers to class methods.
2086
2126
  if (obj.$$eval) {
@@ -2101,7 +2141,7 @@
2101
2141
  }
2102
2142
 
2103
2143
  if (!is_method_body(body)) {
2104
- throw Opal.NameError.$new("undefined method `" + old + "' for class `" + obj.$name() + "'")
2144
+ $raise(Opal.NameError, "undefined method `" + old + "' for class `" + obj.$name() + "'")
2105
2145
  }
2106
2146
  }
2107
2147
 
@@ -2135,7 +2175,7 @@
2135
2175
  // Try to make the browser pick the right name
2136
2176
  alias.displayName = name;
2137
2177
 
2138
- alias.$$arity = body.$$arity;
2178
+ alias.$$arity = body.$$arity == null ? body.length : body.$$arity;
2139
2179
  alias.$$parameters = body.$$parameters;
2140
2180
  alias.$$source_location = body.$$source_location;
2141
2181
  alias.$$alias_of = body;
@@ -2161,11 +2201,11 @@
2161
2201
  }
2162
2202
 
2163
2203
  Opal.alias_native = function(obj, name, native_name) {
2164
- var id = '$' + name,
2204
+ var id = $jsid(name),
2165
2205
  body = obj.$$prototype[native_name];
2166
2206
 
2167
2207
  if (typeof(body) !== "function" || body.$$stub) {
2168
- throw Opal.NameError.$new("undefined native method `" + native_name + "' for class `" + obj.$name() + "'")
2208
+ $raise(Opal.NameError, "undefined native method `" + native_name + "' for class `" + obj.$name() + "'")
2169
2209
  }
2170
2210
 
2171
2211
  Opal.defn(obj, id, body);
@@ -2203,7 +2243,7 @@
2203
2243
 
2204
2244
  Opal.hash_put = function(hash, key, value) {
2205
2245
  if (key.$$is_string) {
2206
- if (!$has_own.call(hash.$$smap, key)) {
2246
+ if (!$has_own(hash.$$smap, key)) {
2207
2247
  hash.$$keys.push(key);
2208
2248
  }
2209
2249
  hash.$$smap[key] = value;
@@ -2213,7 +2253,7 @@
2213
2253
  var key_hash, bucket, last_bucket;
2214
2254
  key_hash = hash.$$by_identity ? Opal.id(key) : key.$hash();
2215
2255
 
2216
- if (!$has_own.call(hash.$$map, key_hash)) {
2256
+ if (!$has_own(hash.$$map, key_hash)) {
2217
2257
  bucket = {key: key, key_hash: key_hash, value: value};
2218
2258
  hash.$$keys.push(bucket);
2219
2259
  hash.$$map[key_hash] = bucket;
@@ -2241,7 +2281,7 @@
2241
2281
 
2242
2282
  Opal.hash_get = function(hash, key) {
2243
2283
  if (key.$$is_string) {
2244
- if ($has_own.call(hash.$$smap, key)) {
2284
+ if ($has_own(hash.$$smap, key)) {
2245
2285
  return hash.$$smap[key];
2246
2286
  }
2247
2287
  return;
@@ -2250,7 +2290,7 @@
2250
2290
  var key_hash, bucket;
2251
2291
  key_hash = hash.$$by_identity ? Opal.id(key) : key.$hash();
2252
2292
 
2253
- if ($has_own.call(hash.$$map, key_hash)) {
2293
+ if ($has_own(hash.$$map, key_hash)) {
2254
2294
  bucket = hash.$$map[key_hash];
2255
2295
 
2256
2296
  while (bucket) {
@@ -2268,7 +2308,7 @@
2268
2308
  if (key.$$is_string) {
2269
2309
  if (typeof key !== "string") key = key.valueOf();
2270
2310
 
2271
- if (!$has_own.call(hash.$$smap, key)) {
2311
+ if (!$has_own(hash.$$smap, key)) {
2272
2312
  return;
2273
2313
  }
2274
2314
 
@@ -2292,7 +2332,7 @@
2292
2332
 
2293
2333
  var key_hash = key.$hash();
2294
2334
 
2295
- if (!$has_own.call(hash.$$map, key_hash)) {
2335
+ if (!$has_own(hash.$$map, key_hash)) {
2296
2336
  return;
2297
2337
  }
2298
2338
 
@@ -2367,7 +2407,7 @@
2367
2407
 
2368
2408
  hash.$$keys[i].key_hash = key_hash;
2369
2409
 
2370
- if (!$has_own.call(hash.$$map, key_hash)) {
2410
+ if (!$has_own(hash.$$map, key_hash)) {
2371
2411
  hash.$$map[key_hash] = hash.$$keys[i];
2372
2412
  continue;
2373
2413
  }
@@ -2408,7 +2448,7 @@
2408
2448
 
2409
2449
  for (i = 0; i < length; i++) {
2410
2450
  if (args[i].length !== 2) {
2411
- throw Opal.ArgumentError.$new("value not of length 2: " + args[i].$inspect());
2451
+ $raise(Opal.ArgumentError, "value not of length 2: " + args[i].$inspect());
2412
2452
  }
2413
2453
 
2414
2454
  key = args[i][0];
@@ -2422,7 +2462,7 @@
2422
2462
  else {
2423
2463
  args = arguments[0];
2424
2464
  for (key in args) {
2425
- if ($has_own.call(args, key)) {
2465
+ if ($has_own(args, key)) {
2426
2466
  value = args[key];
2427
2467
 
2428
2468
  Opal.hash_put(hash, key, value);
@@ -2434,7 +2474,7 @@
2434
2474
  }
2435
2475
 
2436
2476
  if (arguments_length % 2 !== 0) {
2437
- throw Opal.ArgumentError.$new("odd number of arguments for Hash");
2477
+ $raise(Opal.ArgumentError, "odd number of arguments for Hash");
2438
2478
  }
2439
2479
 
2440
2480
  for (i = 0; i < arguments_length; i += 2) {
@@ -2499,7 +2539,7 @@
2499
2539
  // helper that can be used from methods
2500
2540
  function $deny_frozen_access(obj) {
2501
2541
  if (obj.$$frozen) {
2502
- throw Opal.FrozenError.$new("can't modify frozen " + (obj.$class()) + ": " + (obj), Opal.hash2(["receiver"], {"receiver": obj}));
2542
+ $raise(Opal.FrozenError, "can't modify frozen " + (obj.$class()) + ": " + (obj), Opal.hash2(["receiver"], {"receiver": obj}));
2503
2543
  }
2504
2544
  };
2505
2545
  Opal.deny_frozen_access = $deny_frozen_access;
@@ -2701,11 +2741,7 @@
2701
2741
  var message = 'cannot load such file -- ' + path;
2702
2742
 
2703
2743
  if (severity === "error") {
2704
- if (Opal.LoadError) {
2705
- throw Opal.LoadError.$new(message)
2706
- } else {
2707
- throw message
2708
- }
2744
+ $raise(Opal.LoadError, message);
2709
2745
  }
2710
2746
  else if (severity === "warning") {
2711
2747
  console.warn('WARNING: LoadError: ' + message);
@@ -2746,7 +2782,7 @@
2746
2782
  Opal.set_encoding = function(str, name, type) {
2747
2783
  if (typeof type === "undefined") type = "encoding";
2748
2784
  if (typeof str === 'string' || str.$$frozen === true)
2749
- throw Opal.FrozenError.$new("can't modify frozen String");
2785
+ $raise(Opal.FrozenError, "can't modify frozen String");
2750
2786
 
2751
2787
  var encoding = Opal.find_encoding(name);
2752
2788
 
@@ -2761,7 +2797,7 @@
2761
2797
  Opal.find_encoding = function(name) {
2762
2798
  var register = Opal.encodings;
2763
2799
  var encoding = register[name] || register[name.toUpperCase()];
2764
- if (!encoding) throw Opal.ArgumentError.$new("unknown encoding name - " + name);
2800
+ if (!encoding) $raise(Opal.ArgumentError, "unknown encoding name - " + name);
2765
2801
  return encoding;
2766
2802
  }
2767
2803
 
@@ -2883,17 +2919,44 @@
2883
2919
  } else if (kwargs.$$is_hash) {
2884
2920
  return kwargs;
2885
2921
  } else {
2886
- throw Opal.ArgumentError.$new('expected kwargs');
2922
+ $raise(Opal.ArgumentError, 'expected kwargs');
2887
2923
  }
2888
2924
  }
2889
2925
 
2890
2926
  Opal.get_kwarg = function(kwargs, key) {
2891
- if (!$has_own.call(kwargs.$$smap, key)) {
2892
- throw Opal.ArgumentError.$new('missing keyword: '+key);
2927
+ if (!$has_own(kwargs.$$smap, key)) {
2928
+ $raise(Opal.ArgumentError, 'missing keyword: '+key);
2893
2929
  }
2894
2930
  return kwargs.$$smap[key];
2895
2931
  }
2896
2932
 
2933
+ // Arrays of size > 32 elements that contain only strings,
2934
+ // symbols, integers and nils are compiled as a self-extracting
2935
+ // string.
2936
+ Opal.large_array_unpack = function(str) {
2937
+ var array = str.split(","), length = array.length, i;
2938
+ for (i = 0; i < length; i++) {
2939
+ switch(array[i][0]) {
2940
+ case undefined:
2941
+ array[i] = nil
2942
+ break;
2943
+ case '-':
2944
+ case '0':
2945
+ case '1':
2946
+ case '2':
2947
+ case '3':
2948
+ case '4':
2949
+ case '5':
2950
+ case '6':
2951
+ case '7':
2952
+ case '8':
2953
+ case '9':
2954
+ array[i] = +array[i];
2955
+ }
2956
+ }
2957
+ return array;
2958
+ }
2959
+
2897
2960
  // Initialization
2898
2961
  // --------------
2899
2962
  Opal.BasicObject = BasicObject = $allocate_class('BasicObject', null);
@@ -2949,7 +3012,7 @@
2949
3012
 
2950
3013
  // Foward calls to define_method on the top object to Object
2951
3014
  function top_define_method() {
2952
- var args = Opal.slice.call(arguments);
3015
+ var args = $slice(arguments);
2953
3016
  var block = top_define_method.$$p;
2954
3017
  top_define_method.$$p = null;
2955
3018
  return Opal.send(_Object, 'define_method', args, block)
@@ -2960,7 +3023,7 @@
2960
3023
  $const_set(_Object, 'NilClass', Opal.NilClass);
2961
3024
  nil = Opal.nil = new Opal.NilClass();
2962
3025
  nil.$$id = nil_id;
2963
- nil.call = nil.apply = function() { throw Opal.LocalJumpError.$new('no block given'); };
3026
+ nil.call = nil.apply = function() { $raise(Opal.LocalJumpError, 'no block given'); };
2964
3027
  nil.$$frozen = true;
2965
3028
  nil.$$comparable = false;
2966
3029
  Object.seal(nil);