opal 0.6.0 → 0.6.1

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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitmodules +27 -3
  4. data/.rspec +1 -1
  5. data/CHANGELOG.md +29 -5
  6. data/README.md +30 -3
  7. data/Rakefile +18 -9
  8. data/bin/opal +1 -1
  9. data/bin/opal-build +70 -7
  10. data/lib/mspec/opal/rake_task.rb +6 -9
  11. data/lib/opal/cli.rb +2 -2
  12. data/lib/opal/nodes/call.rb +1 -1
  13. data/lib/opal/nodes/def.rb +1 -1
  14. data/lib/opal/nodes/rescue.rb +19 -18
  15. data/lib/opal/parser/grammar.rb +8 -3
  16. data/lib/opal/parser/grammar.y +4 -0
  17. data/lib/opal/parser/lexer.rb +10 -5
  18. data/lib/opal/sprockets/environment.rb +9 -0
  19. data/lib/opal/sprockets/erb.rb +9 -1
  20. data/lib/opal/sprockets/processor.rb +10 -14
  21. data/lib/opal/util.rb +50 -15
  22. data/lib/opal/version.rb +1 -1
  23. data/opal.gemspec +4 -4
  24. data/opal/corelib/enumerable.rb +1 -1
  25. data/opal/corelib/enumerator.rb +7 -3
  26. data/opal/corelib/hash.rb +38 -14
  27. data/opal/corelib/kernel.rb +6 -2
  28. data/opal/corelib/module.rb +15 -1
  29. data/opal/corelib/runtime.js +32 -2
  30. data/opal/corelib/string.rb +103 -53
  31. data/opal/corelib/variables.rb +3 -3
  32. data/spec/cli/fixtures/sprockets_file.js.rb +3 -0
  33. data/spec/cli/parser/literal_spec.rb +5 -0
  34. data/spec/cli/sprockets/environment_spec.rb +14 -0
  35. data/spec/cli/sprockets/erb_spec.rb +25 -0
  36. data/spec/cli/sprockets/processor_spec.rb +28 -0
  37. data/spec/{opal/filters → filters}/bugs/array.rb +29 -9
  38. data/spec/{opal/filters → filters}/bugs/basic_object.rb +2 -0
  39. data/spec/{opal/filters → filters}/bugs/class.rb +1 -0
  40. data/spec/{opal/filters → filters}/bugs/enumerable.rb +6 -2
  41. data/spec/filters/bugs/enumerator.rb +3 -0
  42. data/spec/{opal/filters → filters}/bugs/hash.rb +6 -24
  43. data/spec/{opal/filters → filters}/bugs/kernel.rb +0 -0
  44. data/spec/{opal/filters → filters}/bugs/language.rb +14 -3
  45. data/spec/{opal/filters → filters}/bugs/math.rb +3 -1
  46. data/spec/{opal/filters → filters}/bugs/module.rb +0 -0
  47. data/spec/{opal/filters → filters}/bugs/nil.rb +0 -0
  48. data/spec/{opal/filters → filters}/bugs/numeric.rb +1 -1
  49. data/spec/{opal/filters → filters}/bugs/opal.rb +0 -0
  50. data/spec/filters/bugs/regexp.rb +7 -0
  51. data/spec/{opal/filters → filters}/bugs/set.rb +0 -0
  52. data/spec/{opal/filters → filters}/bugs/singleton.rb +0 -0
  53. data/spec/{opal/filters → filters}/bugs/string.rb +40 -13
  54. data/spec/{opal/filters → filters}/bugs/stringscanner.rb +1 -0
  55. data/spec/{opal/filters → filters}/bugs/struct.rb +7 -2
  56. data/spec/{opal/filters → filters}/bugs/symbol.rb +0 -0
  57. data/spec/{opal/filters → filters}/bugs/time.rb +23 -0
  58. data/spec/{opal/filters → filters}/bugs/unknown.rb +0 -0
  59. data/spec/{opal/filters → filters}/unsupported/encoding.rb +34 -1
  60. data/spec/{opal/filters → filters}/unsupported/enumerator.rb +1 -0
  61. data/spec/{opal/filters → filters}/unsupported/float.rb +0 -0
  62. data/spec/{opal/filters → filters}/unsupported/frozen.rb +3 -2
  63. data/spec/{opal/filters → filters}/unsupported/hash_compare_by_identity.rb +0 -0
  64. data/spec/{opal/filters → filters}/unsupported/integer_size.rb +0 -0
  65. data/spec/{opal/filters → filters}/unsupported/method_added.rb +0 -0
  66. data/spec/{opal/filters → filters}/unsupported/mutable_strings.rb +14 -0
  67. data/spec/{opal/filters → filters}/unsupported/private_constants.rb +0 -0
  68. data/spec/{opal/filters → filters}/unsupported/private_methods.rb +0 -0
  69. data/spec/{opal/filters → filters}/unsupported/random.rb +0 -0
  70. data/spec/{opal/filters → filters}/unsupported/ruby_exe.rb +0 -0
  71. data/spec/{opal/filters → filters}/unsupported/tainted.rb +11 -0
  72. data/spec/{opal/filters → filters}/unsupported/time.rb +0 -0
  73. data/spec/{opal/filters → filters}/unsupported/trusted.rb +14 -0
  74. data/spec/opal/core/kernel/methods_spec.rb +16 -2
  75. data/spec/opal/core/language/string_spec.rb +29 -1
  76. data/spec/opal/core/module/remove_const_spec.rb +1 -1
  77. data/spec/opal/stdlib/erb/erb_spec.rb +3 -3
  78. data/spec/opal/stdlib/native/native_reader_spec.rb +22 -0
  79. data/spec/opal/stdlib/native/native_writer_spec.rb +30 -0
  80. data/spec/rubyspecs +285 -0
  81. data/spec/{opal/spec_helper.rb → spec_helper.rb} +0 -0
  82. data/stdlib/native.rb +21 -0
  83. data/stdlib/opal-parser.rb +14 -3
  84. data/stdlib/promise.rb +2 -2
  85. metadata +113 -97
  86. data/spec/opal/filters/bugs/regexp.rb +0 -5
  87. data/spec/opal/rubyspecs +0 -285
@@ -1,6 +1,6 @@
1
1
  #
2
2
  # DO NOT MODIFY!!!!
3
- # This file is automatically generated by Racc 1.4.9
3
+ # This file is automatically generated by Racc 1.4.11
4
4
  # from Racc grammer file "".
5
5
  #
6
6
 
@@ -2217,7 +2217,7 @@ racc_reduce_table = [
2217
2217
  3, 192, :_reduce_256,
2218
2218
  4, 192, :_reduce_257,
2219
2219
  3, 162, :_reduce_258,
2220
- 4, 162, :_reduce_none,
2220
+ 4, 162, :_reduce_259,
2221
2221
  2, 162, :_reduce_260,
2222
2222
  1, 190, :_reduce_none,
2223
2223
  1, 190, :_reduce_none,
@@ -4004,7 +4004,12 @@ def _reduce_258(val, _values, result)
4004
4004
  result
4005
4005
  end
4006
4006
 
4007
- # reduce 259 omitted
4007
+ def _reduce_259(val, _values, result)
4008
+ val[0] << s(:splat, val[3])
4009
+ result = s(:array, *val[0])
4010
+
4011
+ result
4012
+ end
4008
4013
 
4009
4014
  def _reduce_260(val, _values, result)
4010
4015
  result = s(:splat, val[1])
@@ -700,6 +700,10 @@ rule
700
700
  result = s(:array, *val[0])
701
701
  }
702
702
  | args tCOMMA tSTAR arg_value
703
+ {
704
+ val[0] << s(:splat, val[3])
705
+ result = s(:array, *val[0])
706
+ }
703
707
  | tSTAR arg_value
704
708
  {
705
709
  result = s(:splat, val[1])
@@ -241,6 +241,9 @@ module Opal
241
241
  eos_regx = /[ \t]*#{Regexp.escape(str_parse[:term])}(\r*\n|$)/
242
242
  expand = true
243
243
 
244
+ # Don't escape single-quoted heredoc identifiers
245
+ escape = str_parse[:func] != STR_SQUOTE
246
+
244
247
  if check(eos_regx)
245
248
  scan(/[ \t]*#{Regexp.escape(str_parse[:term])}/)
246
249
 
@@ -272,7 +275,7 @@ module Opal
272
275
  elsif expand && check(/#(?=[\$\@\{])/)
273
276
  break
274
277
  elsif scan(/\\/)
275
- str_buffer << self.read_escape
278
+ str_buffer << (escape ? self.read_escape : scanner.matched)
276
279
  else
277
280
  reg = Regexp.new("[^\#\0\\\\\n]+|.")
278
281
 
@@ -471,9 +474,11 @@ module Opal
471
474
  end
472
475
 
473
476
  def heredoc_identifier
474
- if scan(/(-?)['"]?(\w+)['"]?/)
475
- heredoc = @scanner[2]
476
- self.strterm = new_strterm(STR_DQUOTE, heredoc, heredoc)
477
+ if scan(/(-?)(['"])?(\w+)\2?/)
478
+ escape_method = (@scanner[2] == "'") ? STR_SQUOTE : STR_DQUOTE
479
+ heredoc = @scanner[3]
480
+
481
+ self.strterm = new_strterm(escape_method, heredoc, heredoc)
477
482
  self.strterm[:type] = :heredoc
478
483
 
479
484
  # if ruby code at end of line after heredoc, we have to store it to
@@ -510,7 +515,7 @@ module Opal
510
515
  result = :tIDENTIFIER
511
516
  else
512
517
  if @lex_state == :expr_fname
513
- if scan(/\=/)
518
+ if !check(/\=\>/) and scan(/\=/)
514
519
  result = :tIDENTIFIER
515
520
  matched += scanner.matched
516
521
  end
@@ -1,6 +1,15 @@
1
1
  require 'sprockets'
2
+ require 'opal/sprockets/processor'
3
+ require 'opal/sprockets/erb'
2
4
 
3
5
  module Opal
6
+ # Proccess using Sprockets
7
+ #
8
+ # Opal.process('opal-jquery') # => String
9
+ def self.process asset
10
+ Environment.new[asset].to_s
11
+ end
12
+
4
13
  # Environment is a subclass of Sprockets::Environment which already has our opal
5
14
  # load paths loaded. This makes it easy for stand-alone rack apps, or test runners
6
15
  # that have opal load paths ready to use. You can also add an existing gem's lib
@@ -1,22 +1,30 @@
1
1
  require 'opal'
2
- require 'opal/compiler'
2
+ require 'tilt'
3
+ require 'opal/erb'
3
4
  require 'sprockets'
4
5
 
5
6
  module Opal
6
7
  module ERB
7
8
  class Processor < Tilt::Template
9
+ # vvv BOILERPLATE vvv
8
10
  self.default_mime_type = 'application/javascript'
9
11
 
10
12
  def self.engine_initialized?
11
13
  true
12
14
  end
13
15
 
16
+ def self.version
17
+ ::Opal::VERSION
18
+ end
19
+
14
20
  def initialize_engine
15
21
  require_template_library 'opal'
16
22
  end
17
23
 
18
24
  def prepare
19
25
  end
26
+ # ^^^ BOILERPLATE ^^^
27
+
20
28
 
21
29
  def evaluate(context, locals, &block)
22
30
  context.require_asset 'erb'
@@ -5,13 +5,6 @@ require 'opal/version'
5
5
  $OPAL_SOURCE_MAPS = {}
6
6
 
7
7
  module Opal
8
- # Proccess using Sprockets
9
- #
10
- # Opal.process('opal-jquery') # => String
11
- def self.process asset
12
- Environment.new[asset].to_s
13
- end
14
-
15
8
  # The Processor class is used to make ruby files (with rb or opal extensions)
16
9
  # available to any sprockets based server. Processor will then get passed any
17
10
  # ruby source file to build. There are some options you can override globally
@@ -26,6 +19,7 @@ module Opal
26
19
  # * irb_enabled [false by default]
27
20
  #
28
21
  class Processor < Tilt::Template
22
+ # vvv BOILERPLATE vvv
29
23
  self.default_mime_type = 'application/javascript'
30
24
 
31
25
  def self.engine_initialized?
@@ -36,6 +30,15 @@ module Opal
36
30
  ::Opal::VERSION
37
31
  end
38
32
 
33
+ def initialize_engine
34
+ require_template_library 'opal'
35
+ end
36
+
37
+ def prepare
38
+ end
39
+ # ^^^ BOILERPLATE ^^^
40
+
41
+
39
42
  class << self
40
43
  attr_accessor :method_missing_enabled
41
44
  attr_accessor :arity_check_enabled
@@ -60,13 +63,6 @@ module Opal
60
63
  @stubbed_files ||= Set.new
61
64
  end
62
65
 
63
- def initialize_engine
64
- require_template_library 'opal'
65
- end
66
-
67
- def prepare
68
- end
69
-
70
66
  def evaluate(context, locals, &block)
71
67
  options = {
72
68
  :method_missing => self.class.method_missing_enabled,
data/lib/opal/util.rb CHANGED
@@ -4,26 +4,61 @@ module Opal
4
4
 
5
5
  # Used for uglifying source to minify
6
6
  def uglify(str)
7
- IO.popen('uglifyjs 2> /dev/null', 'r+') do |i|
8
- i.puts str
9
- i.close_write
10
- return i.read
11
- end
12
- rescue Errno::ENOENT, Errno::EPIPE
13
- $stderr.puts '"uglifyjs" command not found (install with: "npm install -g uglify-js")'
14
- nil
7
+ uglifyjs = DigestSourceCommand.new(:uglifyjs, nil, ' (install with: "npm install -g uglify-js")')
8
+ uglifyjs.digest(str)
15
9
  end
16
10
 
17
11
  # Gzip code to check file size
18
12
  def gzip(str)
19
- IO.popen('gzip -f 2> /dev/null', 'r+') do |i|
20
- i.puts str
21
- i.close_write
22
- return i.read
13
+ gzip = DigestSourceCommand.new(:gzip, '-f', ', it is required to produce the .gz version')
14
+ gzip.digest(str)
15
+ end
16
+
17
+
18
+ class DigestSourceCommand
19
+ def initialize(command, options, message)
20
+ @command, @options, @message = command, options, message
21
+ end
22
+ attr_reader :command, :options, :message
23
+
24
+ def digest(source)
25
+ return unless command_installed? command, message
26
+ IO.popen("#{command} #{options} #{hide_stderr}", 'r+') do |i|
27
+ i.puts source
28
+ i.close_write
29
+ i.read
30
+ end
31
+ end
32
+
33
+
34
+ private
35
+
36
+ def hide_stderr
37
+ if (/mswin|mingw/ =~ RUBY_PLATFORM).nil?
38
+ '2> /dev/null'
39
+ else
40
+ '2> nul'
41
+ end
42
+ end
43
+
44
+ # Code from http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
45
+ def which(cmd)
46
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
47
+ ENV['PATH'].split(File::PATH_SEPARATOR).find do |path|
48
+ exts.find { |ext|
49
+ exe = File.join(path, "#{cmd}#{ext}")
50
+ exe if File.executable? exe
51
+ }
52
+ end
53
+ end
54
+
55
+ INSTALLED = {}
56
+ def command_installed?(cmd, install_comment)
57
+ command_installed = INSTALLED[cmd.to_s] ||= which(cmd)
58
+ $stderr.puts %Q("#{cmd}" command not found#{install_comment}) unless command_installed
59
+ command_installed
23
60
  end
24
- rescue Errno::ENOENT, Errno::EPIPE
25
- $stderr.puts '"gzip" command not found, it is required to produce the .gz version'
26
- nil
27
61
  end
62
+
28
63
  end
29
64
  end
data/lib/opal/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Opal
2
- VERSION = '0.6.0'
2
+ VERSION = '0.6.1'
3
3
  end
data/opal.gemspec CHANGED
@@ -13,10 +13,10 @@ Gem::Specification.new do |s|
13
13
  s.description = 'Ruby runtime and core library for javascript.'
14
14
  s.license = 'MIT'
15
15
 
16
- s.files = `git ls-files`.split("\n")
17
- s.executables = ['opal']
18
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
- s.require_paths = ['lib']
16
+ s.files = `git ls-files`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.require_paths = ['lib']
20
20
 
21
21
  s.add_dependency 'source_map'
22
22
  s.add_dependency 'sprockets'
@@ -664,7 +664,7 @@ module Enumerable
664
664
 
665
665
  self.$each();
666
666
 
667
- return result;
667
+ return result == undefined ? nil : result;
668
668
  }
669
669
  end
670
670
 
@@ -35,10 +35,14 @@ class Enumerator
35
35
  end
36
36
  end
37
37
 
38
- def each(&block)
39
- return self unless block
38
+ def each(*args, &block)
39
+ return self if block.nil? && args.empty?
40
40
 
41
- @object.__send__(@method, *@args, &block)
41
+ args = @args + args
42
+
43
+ return self.class.new(@object, @method, *args) if block.nil?
44
+
45
+ @object.__send__(@method, *args, &block)
42
46
  end
43
47
 
44
48
  def size
data/opal/corelib/hash.rb CHANGED
@@ -13,6 +13,8 @@ class Hash
13
13
 
14
14
  hash.map = {};
15
15
  hash.keys = [];
16
+ hash.none = nil;
17
+ hash.proc = nil;
16
18
 
17
19
  return hash;
18
20
  }
@@ -20,14 +22,8 @@ class Hash
20
22
 
21
23
  def initialize(defaults = undefined, &block)
22
24
  %x{
23
- if (defaults != null) {
24
- self.none = defaults;
25
- }
26
- else if (block !== nil) {
27
- self.proc = block;
28
- }
29
-
30
- return self;
25
+ self.none = (defaults === undefined ? nil : defaults);
26
+ self.proc = block;
31
27
  }
32
28
  end
33
29
 
@@ -50,8 +46,7 @@ class Hash
50
46
 
51
47
  for (var i = 0, length = self.keys.length; i < length; i++) {
52
48
  var key = self.keys[i], obj = map[key], obj2 = map2[key];
53
-
54
- if (#{`obj` != `obj2`}) {
49
+ if (obj2 === undefined || #{`obj` != `obj2`}) {
55
50
  return false;
56
51
  }
57
52
  }
@@ -141,11 +136,19 @@ class Hash
141
136
  end
142
137
 
143
138
  def default(val = undefined)
144
- @none
139
+ %x{
140
+ if (val !== undefined && self.proc !== nil) {
141
+ return #{@proc.call(self, val)};
142
+ }
143
+ return self.none;
144
+ }
145
145
  end
146
146
 
147
147
  def default=(object)
148
- @none = object
148
+ %x{
149
+ self.proc = nil;
150
+ return (self.none = object);
151
+ }
149
152
  end
150
153
 
151
154
  def default_proc
@@ -153,10 +156,20 @@ class Hash
153
156
  end
154
157
 
155
158
  def default_proc=(proc)
156
- @proc = proc
159
+ %x{
160
+ if (proc !== nil) {
161
+ proc = #{Opal.coerce_to!(proc, Proc, :to_proc)};
162
+
163
+ if (#{proc.lambda?} && #{proc.arity.abs} != 2) {
164
+ #{raise TypeError, "default_proc takes two arguments"};
165
+ }
166
+ }
167
+ self.none = nil;
168
+ return (self.proc = proc);
169
+ }
157
170
  end
158
171
 
159
- def delete(key)
172
+ def delete(key, &block)
160
173
  %x{
161
174
  var map = self.map, result = map[key];
162
175
 
@@ -167,6 +180,9 @@ class Hash
167
180
  return result;
168
181
  }
169
182
 
183
+ if (block !== nil) {
184
+ return #{block.call(key)};
185
+ }
170
186
  return nil;
171
187
  }
172
188
  end
@@ -448,6 +464,10 @@ class Hash
448
464
 
449
465
  def merge(other, &block)
450
466
  %x{
467
+ if (! #{Hash === other}) {
468
+ other = #{Opal.coerce_to!(other, Hash, :to_hash)};
469
+ }
470
+
451
471
  var keys = self.keys, map = self.map,
452
472
  result = $opal.hash(), keys2 = result.keys, map2 = result.map;
453
473
 
@@ -491,6 +511,10 @@ class Hash
491
511
 
492
512
  def merge!(other, &block)
493
513
  %x{
514
+ if (! #{Hash === other}) {
515
+ other = #{Opal.coerce_to!(other, Hash, :to_hash)};
516
+ }
517
+
494
518
  var keys = self.keys, map = self.map,
495
519
  keys2 = other.keys, map2 = other.map;
496
520
 
@@ -44,8 +44,9 @@ module Kernel
44
44
  continue;
45
45
  }
46
46
  }
47
-
48
- methods.push(key.substr(1));
47
+ if (self[key].rb_stub === undefined) {
48
+ methods.push(key.substr(1));
49
+ }
49
50
  }
50
51
  }
51
52
 
@@ -139,6 +140,8 @@ module Kernel
139
140
  Enumerator.for(self, method, *args, &block)
140
141
  end
141
142
 
143
+ alias to_enum enum_for
144
+
142
145
  def equal?(other)
143
146
  `self === other`
144
147
  end
@@ -464,6 +467,7 @@ module Kernel
464
467
  exception = #{exception.new string};
465
468
  }
466
469
 
470
+ #{$! = exception};
467
471
  throw exception;
468
472
  }
469
473
  end