opal 0.7.0.beta1 → 0.7.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitmodules +1 -1
  4. data/.inch.yml +19 -0
  5. data/.travis.yml +10 -7
  6. data/CHANGELOG.md +23 -0
  7. data/README.md +2 -2
  8. data/Rakefile +43 -1
  9. data/bin/opal +6 -1
  10. data/lib/mspec/opal/rake_task.rb +10 -31
  11. data/lib/mspec/opal/runner.rb +44 -1
  12. data/lib/mspec/opal/special_calls.rb +25 -0
  13. data/lib/opal/builder.rb +1 -1
  14. data/lib/opal/builder_processors.rb +4 -23
  15. data/lib/opal/cli.rb +17 -11
  16. data/lib/opal/cli_options.rb +1 -1
  17. data/lib/opal/cli_runners.rb +1 -0
  18. data/lib/opal/cli_runners/apple_script.rb +65 -0
  19. data/lib/opal/cli_runners/nodejs.rb +9 -3
  20. data/lib/opal/cli_runners/phantomjs.rb +2 -2
  21. data/lib/opal/cli_runners/server.rb +7 -5
  22. data/lib/opal/compiler.rb +1 -1
  23. data/lib/opal/nodes/call.rb +3 -2
  24. data/lib/opal/nodes/constants.rb +3 -3
  25. data/lib/opal/nodes/def.rb +7 -7
  26. data/lib/opal/nodes/defined.rb +2 -2
  27. data/lib/opal/nodes/definitions.rb +1 -1
  28. data/lib/opal/nodes/literal.rb +1 -1
  29. data/lib/opal/nodes/logic.rb +1 -1
  30. data/lib/opal/nodes/masgn.rb +1 -1
  31. data/lib/opal/nodes/module.rb +1 -1
  32. data/lib/opal/nodes/rescue.rb +1 -1
  33. data/lib/opal/nodes/scope.rb +1 -1
  34. data/lib/opal/nodes/super.rb +3 -3
  35. data/lib/opal/nodes/top.rb +11 -9
  36. data/lib/opal/nodes/variables.rb +39 -6
  37. data/lib/opal/nodes/yield.rb +3 -3
  38. data/lib/opal/parser.rb +3 -1
  39. data/lib/opal/parser/lexer.rb +8 -2
  40. data/lib/opal/paths.rb +13 -3
  41. data/lib/opal/sprockets/server.rb +1 -1
  42. data/lib/opal/version.rb +1 -1
  43. data/opal.gemspec +1 -1
  44. data/opal/corelib/array.rb +29 -20
  45. data/opal/corelib/array/inheritance.rb +3 -3
  46. data/opal/corelib/basic_object.rb +3 -1
  47. data/opal/corelib/class.rb +1 -1
  48. data/opal/corelib/comparable.rb +6 -5
  49. data/opal/corelib/dir.rb +4 -4
  50. data/opal/corelib/enumerable.rb +25 -25
  51. data/opal/corelib/enumerator.rb +16 -14
  52. data/opal/corelib/error.rb +13 -4
  53. data/opal/corelib/hash.rb +511 -162
  54. data/opal/corelib/helpers.rb +1 -1
  55. data/opal/corelib/kernel.rb +60 -44
  56. data/opal/corelib/match_data.rb +1 -10
  57. data/opal/corelib/method.rb +1 -1
  58. data/opal/corelib/module.rb +62 -32
  59. data/opal/corelib/nil_class.rb +1 -6
  60. data/opal/corelib/numeric.rb +6 -3
  61. data/opal/corelib/proc.rb +1 -1
  62. data/opal/corelib/regexp.rb +15 -6
  63. data/opal/corelib/runtime.js +57 -36
  64. data/opal/corelib/string.rb +38 -2
  65. data/opal/corelib/string/inheritance.rb +3 -3
  66. data/opal/corelib/struct.rb +1 -1
  67. data/opal/corelib/time.rb +46 -3
  68. data/spec/filters/bugs/date.rb +15 -0
  69. data/spec/filters/bugs/enumerator.rb +7 -0
  70. data/spec/filters/bugs/exception.rb +12 -0
  71. data/spec/filters/bugs/hash.rb +0 -18
  72. data/spec/filters/bugs/match_data.rb +13 -0
  73. data/spec/filters/bugs/module.rb +13 -0
  74. data/spec/filters/bugs/numeric.rb +2 -0
  75. data/spec/filters/bugs/regexp.rb +0 -2
  76. data/spec/filters/bugs/stringscanner.rb +8 -0
  77. data/spec/filters/bugs/time.rb +1 -1
  78. data/spec/filters/unsupported/float.rb +1 -0
  79. data/spec/filters/unsupported/symbols.rb +10 -0
  80. data/spec/filters/unsupported/tainted.rb +3 -0
  81. data/spec/filters/unsupported/trusted.rb +3 -0
  82. data/spec/lib/compiler_spec.rb +2 -2
  83. data/spec/lib/parser/call_spec.rb +7 -0
  84. data/spec/opal/core/date_spec.rb +49 -8
  85. data/spec/opal/core/exception_spec.rb +13 -0
  86. data/spec/opal/core/fixtures/require_tree_files/nested/nested 1.rb +1 -0
  87. data/spec/opal/core/fixtures/require_tree_files/nested/nested 2.rb +1 -0
  88. data/spec/opal/core/fixtures/require_tree_files/other/other 1.rb +1 -0
  89. data/spec/opal/core/kernel/require_tree_spec.rb +3 -1
  90. data/spec/opal/core/language/predefined_spec.rb +43 -0
  91. data/spec/opal/stdlib/promise/rescue_spec.rb +9 -0
  92. data/spec/opal/stdlib/promise/then_spec.rb +9 -0
  93. data/spec/opal/stdlib/promise/trace_spec.rb +9 -0
  94. data/spec/rubyspecs +40 -19
  95. data/spec/spec_helper.rb +10 -5
  96. data/stdlib/date.rb +68 -8
  97. data/stdlib/fileutils.rb +0 -0
  98. data/stdlib/iconv.rb +0 -0
  99. data/stdlib/json.rb +16 -3
  100. data/stdlib/native.rb +36 -17
  101. data/stdlib/nodejs.rb +3 -0
  102. data/stdlib/nodejs/dir.rb +1 -1
  103. data/stdlib/nodejs/file.rb +2 -2
  104. data/stdlib/nodejs/io.rb +1 -1
  105. data/stdlib/nodejs/process.rb +2 -2
  106. data/stdlib/nodejs/require.rb +5 -7
  107. data/stdlib/nodejs/runtime.rb +3 -2
  108. data/stdlib/pathname.rb +25 -1
  109. data/stdlib/promise.rb +16 -0
  110. data/stdlib/set.rb +48 -4
  111. data/stdlib/strscan.rb +12 -1
  112. data/stdlib/yaml.rb +1 -0
  113. metadata +27 -7
  114. data/spec/opal/core/language/symbol_spec.rb +0 -40
@@ -53,7 +53,7 @@ module Opal
53
53
  compare = a <=> b
54
54
 
55
55
  if `compare === nil`
56
- raise ArgumentError, "comparison of #{a.class.name} with #{b.class.name} failed"
56
+ raise ArgumentError, "comparison of #{a.class} with #{b.class} failed"
57
57
  end
58
58
 
59
59
  compare
@@ -26,7 +26,7 @@ module Kernel
26
26
  var meth = self['$' + name];
27
27
 
28
28
  if (!meth || meth.$$stub) {
29
- #{raise NameError, "undefined method `#{name}' for class `#{self.class.name}'"};
29
+ #{raise NameError, "undefined method `#{name}' for class `#{self.class}'"};
30
30
  }
31
31
 
32
32
  return #{Method.new(self, `meth`, name)};
@@ -40,7 +40,7 @@ module Kernel
40
40
  for (var key in self) {
41
41
  if (key[0] == "$" && typeof(self[key]) === "function") {
42
42
  if (all == false || all === nil) {
43
- if (!$opal.hasOwnProperty.call(self, key)) {
43
+ if (!Opal.hasOwnProperty.call(self, key)) {
44
44
  continue;
45
45
  }
46
46
  }
@@ -288,8 +288,17 @@ module Kernel
288
288
  }
289
289
  end
290
290
 
291
+ def freeze
292
+ @___frozen___ = true
293
+ self
294
+ end
295
+
296
+ def frozen?
297
+ @___frozen___ || false
298
+ end
299
+
291
300
  def hash
292
- `self.$$id`
301
+ `[self.$$class.$$name,#{`self.$$class`.__id__},#{__id__}].join(':')`
293
302
  end
294
303
 
295
304
  def initialize_copy(other)
@@ -304,7 +313,7 @@ module Kernel
304
313
  end
305
314
 
306
315
  def instance_variable_defined?(name)
307
- `$opal.hasOwnProperty.call(self, name.substr(1))`
316
+ `Opal.hasOwnProperty.call(self, name.substr(1))`
308
317
  end
309
318
 
310
319
  def instance_variable_get(name)
@@ -384,7 +393,7 @@ module Kernel
384
393
  end
385
394
 
386
395
  def is_a?(klass)
387
- `$opal.is_a(self, klass)`
396
+ `Opal.is_a(self, klass)`
388
397
  end
389
398
 
390
399
  alias kind_of? is_a?
@@ -395,6 +404,10 @@ module Kernel
395
404
  block
396
405
  end
397
406
 
407
+ def load(file)
408
+ `Opal.load(Opal.normalize_loadable_path(#{file}))`
409
+ end
410
+
398
411
  def loop(&block)
399
412
  %x{
400
413
  while (true) {
@@ -489,8 +502,6 @@ module Kernel
489
502
  }
490
503
  end
491
504
 
492
- alias srand rand
493
-
494
505
  def respond_to?(name, include_all = false)
495
506
  return true if respond_to_missing?(name)
496
507
 
@@ -505,65 +516,70 @@ module Kernel
505
516
  false
506
517
  end
507
518
 
519
+ def respond_to_missing?(method_name)
520
+ false
521
+ end
522
+
523
+ def require(file)
524
+ `Opal.require(Opal.normalize_loadable_path(#{file}))`
525
+ end
526
+
527
+ def require_relative(file)
528
+ file = File.expand_path File.join(`Opal.current_file`, '..', file)
529
+
530
+ `Opal.require(Opal.normalize_loadable_path(#{file}))`
531
+ end
532
+
533
+ # `path` should be the full path to be found in registered modules (`Opal.modules`)
534
+ def require_tree(path)
535
+ path = File.expand_path(path)
536
+
537
+ %x{
538
+ for (var name in Opal.modules) {
539
+ if (#{`name`.start_with?(path)}) {
540
+ Opal.require(name);
541
+ }
542
+ }
543
+ }
544
+
545
+ nil
546
+ end
547
+
508
548
  alias send __send__
509
549
  alias public_send __send__
510
550
 
511
551
  def singleton_class
512
- %x{$opal.get_singleton_class(self)}
552
+ %x{Opal.get_singleton_class(self)}
513
553
  end
514
554
 
515
555
  alias sprintf format
516
556
 
557
+ alias srand rand
558
+
517
559
  def String(str)
518
560
  `String(str)`
519
561
  end
520
562
 
521
- def tap(&block)
522
- yield self
523
- self
524
- end
525
-
526
- def to_proc
563
+ def taint
527
564
  self
528
565
  end
529
566
 
530
- def to_s
531
- `"#<" + #{self.class.name} + ":" + self.$$id + ">"`
567
+ def tainted?
568
+ false
532
569
  end
533
570
 
534
- def freeze
535
- @___frozen___ = true
571
+ def tap(&block)
572
+ yield self
536
573
  self
537
574
  end
538
575
 
539
- def frozen?
540
- @___frozen___ || false
541
- end
542
-
543
- def respond_to_missing?(method_name)
544
- false
545
- end
546
-
547
- def require file
548
- `$opal.require( $opal.normalize_loadable_path(#{file}) )`
576
+ def to_proc
577
+ self
549
578
  end
550
579
 
551
- # `path` should be the ful path to be found in registered modules (`Opal.modules`)
552
- def require_tree path
553
- %x{
554
- var file_name, file_names = Object.keys($opal.modules);
555
- path = path.replace(/\/?$/, '/');
556
- for (var i = 0; i < file_names.length; i++) {
557
- file_name = file_names[i];
558
- if (file_name['$start_with?'](path)) {
559
- $opal.require(file_name);
560
- }
561
- }
562
- }
563
- nil
580
+ def to_s
581
+ "#<#{self.class}:0x#{__id__.to_s(16)}>"
564
582
  end
565
583
 
566
- def load file
567
- `$opal.load( $opal.normalize_loadable_path(#{file}) )`
568
- end
584
+ alias untaint taint
569
585
  end
@@ -1,17 +1,8 @@
1
1
  class MatchData
2
2
  attr_reader :post_match, :pre_match, :regexp, :string
3
3
 
4
- def self.new(regexp, match_groups)
5
- data = super(regexp, match_groups)
6
-
7
- $` = data.pre_match
8
- $' = data.post_match
9
- $~ = data
10
-
11
- data
12
- end
13
-
14
4
  def initialize(regexp, match_groups)
5
+ $~ = self
15
6
  @regexp = regexp
16
7
  @begin = `match_groups.index`
17
8
  @string = `match_groups.input`
@@ -31,7 +31,7 @@ class Method
31
31
  end
32
32
 
33
33
  def inspect
34
- "#<Method: #{@obj.class.name}##@name}>"
34
+ "#<Method: #{@obj.class}##@name}>"
35
35
  end
36
36
  end
37
37
 
@@ -10,7 +10,7 @@ class Module
10
10
  klass.$$proto = {};
11
11
 
12
12
  // inherit scope from parent
13
- $opal.create_scope(Opal.Module.$$scope, klass);
13
+ Opal.create_scope(Opal.Module.$$scope, klass);
14
14
 
15
15
  if (block !== nil) {
16
16
  var block_self = block.$$s;
@@ -26,7 +26,7 @@ class Module
26
26
  def ===(object)
27
27
  return false if `object == null`
28
28
 
29
- `$opal.is_a(object, self)`
29
+ `Opal.is_a(object, self)`
30
30
  end
31
31
 
32
32
  def <(other)
@@ -50,7 +50,7 @@ class Module
50
50
  self.$$proto['$' + newname] = self.$$proto['$' + oldname];
51
51
 
52
52
  if (self.$$methods) {
53
- $opal.donate(self, ['$' + newname ])
53
+ Opal.donate(self, ['$' + newname ])
54
54
  }
55
55
  }
56
56
  self
@@ -99,7 +99,7 @@ class Module
99
99
  }
100
100
  else {
101
101
  proto['$' + name] = func;
102
- $opal.donate(self, ['$' + name ]);
102
+ Opal.donate(self, ['$' + name ]);
103
103
  }
104
104
  })(names[i]);
105
105
  }
@@ -121,7 +121,7 @@ class Module
121
121
  }
122
122
  else {
123
123
  proto['$' + name + '='] = func;
124
- $opal.donate(self, ['$' + name + '=']);
124
+ Opal.donate(self, ['$' + name + '=']);
125
125
  }
126
126
  })(names[i]);
127
127
  }
@@ -198,17 +198,18 @@ class Module
198
198
 
199
199
  def const_missing(const)
200
200
  %x{
201
- var autoloader;
201
+ if (self.$$autoload) {
202
+ var file = self.$$autoload[#{const}];
202
203
 
203
- if (self.$$autoload && (autoloader = self.$$autoload[#{const}])) {
204
- self.$require(autoloader);
205
- return self.$$scope.get(#{const});
204
+ if (file) {
205
+ self.$require(file);
206
+
207
+ return #{const_get const};
208
+ }
206
209
  }
207
210
  }
208
211
 
209
- name = `self.$$name`
210
-
211
- raise NameError, "uninitialized constant #{name}::#{const}"
212
+ raise NameError, "uninitialized constant #{self}::#{const}"
212
213
  end
213
214
 
214
215
  def const_set(name, value)
@@ -220,10 +221,9 @@ class Module
220
221
  raise TypeError, 'conversion with #to_str failed'
221
222
  end
222
223
 
223
- %x{
224
- $opal.casgn(self, name, value);
225
- return #{value}
226
- }
224
+ `Opal.casgn(self, name, value)`
225
+
226
+ value
227
227
  end
228
228
 
229
229
  def define_method(name, method = undefined, &block)
@@ -242,7 +242,7 @@ class Module
242
242
  block.$$def = block;
243
243
 
244
244
  self.$$proto[jsid] = block;
245
- $opal.donate(self, [jsid]);
245
+ Opal.donate(self, [jsid]);
246
246
 
247
247
  return name;
248
248
  }
@@ -254,8 +254,8 @@ class Module
254
254
  var current = self.$$proto[jsid];
255
255
  delete self.$$proto[jsid];
256
256
 
257
- // Check if we need to reverse $opal.donate
258
- // $opal.retire(self, [jsid]);
257
+ // Check if we need to reverse Opal.donate
258
+ // Opal.retire(self, [jsid]);
259
259
  return self;
260
260
  }
261
261
  end
@@ -305,20 +305,37 @@ class Module
305
305
 
306
306
  def instance_methods(include_super = false)
307
307
  %x{
308
- var methods = [], proto = self.$$proto;
308
+ var methods = [],
309
+ proto = self.$$proto;
309
310
 
310
- for (var prop in self.$$proto) {
311
- if (!include_super && !proto.hasOwnProperty(prop)) {
311
+ for (var prop in proto) {
312
+ if (!prop.charAt(0) === '$') {
312
313
  continue;
313
314
  }
314
315
 
315
- if (!include_super && proto[prop].$$donated) {
316
+ if (typeof(proto[prop]) !== "function") {
316
317
  continue;
317
318
  }
318
319
 
319
- if (prop.charAt(0) === '$') {
320
- methods.push(prop.substr(1));
320
+ if (proto[prop].$$stub) {
321
+ continue;
321
322
  }
323
+
324
+ if (!self.$$is_mod) {
325
+ if (self !== Opal.BasicObject && proto[prop] === Opal.BasicObject.$$proto[prop]) {
326
+ continue;
327
+ }
328
+
329
+ if (!include_super && !proto.hasOwnProperty(prop)) {
330
+ continue;
331
+ }
332
+
333
+ if (!include_super && proto[prop].$$donated) {
334
+ continue;
335
+ }
336
+ }
337
+
338
+ methods.push(prop.substr(1));
322
339
  }
323
340
 
324
341
  return methods;
@@ -375,10 +392,15 @@ class Module
375
392
 
376
393
  def module_function(*methods)
377
394
  %x{
378
- for (var i = 0, length = methods.length; i < length; i++) {
379
- var meth = methods[i], func = self.$$proto['$' + meth];
395
+ if (methods.length === 0) {
396
+ self.$$module_function = true;
397
+ }
398
+ else {
399
+ for (var i = 0, length = methods.length; i < length; i++) {
400
+ var meth = methods[i], func = self.$$proto['$' + meth];
380
401
 
381
- self.constructor.prototype['$' + meth] = func;
402
+ self.constructor.prototype['$' + meth] = func;
403
+ }
382
404
  }
383
405
 
384
406
  return self;
@@ -402,7 +424,7 @@ class Module
402
424
 
403
425
  base = base.$$base_module;
404
426
 
405
- if (base === $opal.Object) {
427
+ if (base === Opal.Object) {
406
428
  break;
407
429
  }
408
430
  }
@@ -415,7 +437,14 @@ class Module
415
437
  }
416
438
  end
417
439
 
418
- def public(*)
440
+ def public(*methods)
441
+ %x{
442
+ if (methods.length === 0) {
443
+ self.$$module_function = false;
444
+ }
445
+
446
+ return nil;
447
+ }
419
448
  end
420
449
 
421
450
  alias private public
@@ -452,11 +481,12 @@ class Module
452
481
  end
453
482
 
454
483
  def to_s
455
- name.to_s
484
+ name || "#<#{`self.$$is_mod ? 'Module' : 'Class'`}:0x#{__id__.to_s(16)}>"
456
485
  end
457
486
 
458
487
  def undef_method(symbol)
459
- `$opal.add_stub_for(self.$$proto, "$" + symbol)`
488
+ `Opal.add_stub_for(self.$$proto, "$" + symbol)`
489
+
460
490
  self
461
491
  end
462
492
  end
@@ -40,7 +40,7 @@ class NilClass
40
40
  end
41
41
 
42
42
  def to_h
43
- `$opal.hash()`
43
+ `Opal.hash()`
44
44
  end
45
45
 
46
46
  def to_i
@@ -52,11 +52,6 @@ class NilClass
52
52
  def to_s
53
53
  ''
54
54
  end
55
-
56
- def object_id
57
- `#{NilClass}.$$id || (#{NilClass}.$$id = $opal.uid())`
58
- end
59
- alias hash object_id
60
55
  end
61
56
 
62
57
  NIL = nil
@@ -312,7 +312,7 @@ class Numeric
312
312
  end
313
313
 
314
314
  def hash
315
- `self.toString()`
315
+ `'Numeric:'+self.toString()`
316
316
  end
317
317
 
318
318
  def integer?
@@ -376,8 +376,11 @@ class Numeric
376
376
  `self - 1`
377
377
  end
378
378
 
379
- def round
380
- `Math.round(self)`
379
+ def round(ndigits=0)
380
+ %x{
381
+ var scale = Math.pow(10, ndigits);
382
+ return Math.round(self * scale) / scale;
383
+ }
381
384
  end
382
385
 
383
386
  def step(limit, step = 1, &block)