opal 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
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