opal 0.3.44 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/.travis.yml +0 -1
  2. data/CHANGELOG.md +52 -0
  3. data/README.md +3 -3
  4. data/Rakefile +32 -8
  5. data/bin/opal +69 -16
  6. data/config.ru +1 -1
  7. data/examples/native/app/app.rb +28 -9
  8. data/examples/rack/app/app.rb +1 -1
  9. data/lib/opal.rb +0 -1
  10. data/lib/opal/cli.rb +106 -0
  11. data/lib/opal/lexer.rb +4 -2
  12. data/lib/opal/parser.rb +603 -360
  13. data/lib/opal/processor.rb +20 -8
  14. data/lib/opal/server.rb +47 -0
  15. data/lib/opal/source_map.rb +63 -0
  16. data/lib/opal/sprockets_parser.rb +77 -0
  17. data/lib/opal/sprockets_source_map_header.rb +21 -0
  18. data/lib/opal/target_scope.rb +14 -7
  19. data/lib/opal/version.rb +1 -1
  20. data/opal.gemspec +2 -0
  21. data/opal/opal-browser/script_loader.rb +7 -7
  22. data/opal/opal-parser.js.erb +2 -2
  23. data/opal/opal-source-maps.js.erb +2 -0
  24. data/opal/opal.rb +3 -4
  25. data/opal/opal/array.rb +31 -28
  26. data/opal/opal/boolean.rb +4 -0
  27. data/opal/opal/class.rb +14 -5
  28. data/opal/opal/enumerable.rb +68 -8
  29. data/opal/opal/error.rb +1 -1
  30. data/opal/opal/hash.rb +15 -18
  31. data/opal/opal/kernel.rb +24 -10
  32. data/opal/opal/native.rb +31 -0
  33. data/opal/opal/nil_class.rb +7 -2
  34. data/opal/opal/numeric.rb +10 -1
  35. data/opal/opal/proc.rb +4 -0
  36. data/opal/opal/range.rb +1 -1
  37. data/opal/opal/regexp.rb +13 -3
  38. data/opal/opal/runtime.js +134 -51
  39. data/opal/opal/string.rb +45 -22
  40. data/opal/opal/time.rb +25 -7
  41. data/opal/source_map.rb +63 -0
  42. data/opal/source_map/generator.rb +251 -0
  43. data/opal/source_map/parser.rb +102 -0
  44. data/opal/source_map/vlq.rb +122 -0
  45. data/opal/strscan.rb +30 -12
  46. data/spec/opal/class/_inherited_spec.rb +1 -1
  47. data/spec/{rubyspec/core → opal}/class/bridge_class_spec.rb +5 -3
  48. data/spec/{rubyspec/core → opal}/class/extend_spec.rb +0 -0
  49. data/spec/{rubyspec/core → opal}/class/instance_methods_spec.rb +0 -0
  50. data/spec/{rubyspec/core → opal}/class/last_value_spec.rb +0 -1
  51. data/spec/{rubyspec/core → opal}/json/parse_spec.rb +0 -0
  52. data/spec/{rubyspec/core/kernel/block_given.rb → opal/kernel/block_given_spec.rb} +0 -0
  53. data/spec/{rubyspec/core → opal}/kernel/class_spec.rb +0 -0
  54. data/spec/{rubyspec/core → opal}/kernel/extend_spec.rb +0 -0
  55. data/spec/{rubyspec/core → opal}/kernel/format_spec.rb +0 -0
  56. data/spec/opal/kernel/freeze_spec.rb +15 -0
  57. data/spec/{rubyspec/core → opal}/kernel/match_spec.rb +0 -0
  58. data/spec/{rubyspec/core → opal}/kernel/method_spec.rb +0 -0
  59. data/spec/{rubyspec/core → opal}/kernel/methods_spec.rb +0 -0
  60. data/spec/{rubyspec/core → opal}/kernel/nil_spec.rb +0 -0
  61. data/spec/{rubyspec/core → opal}/kernel/p_spec.rb +0 -0
  62. data/spec/{rubyspec/core → opal}/kernel/printf_spec.rb +0 -0
  63. data/spec/{rubyspec/core → opal}/kernel/proc_spec.rb +0 -0
  64. data/spec/{rubyspec/core → opal}/kernel/rand_spec.rb +0 -0
  65. data/spec/{rubyspec/core → opal}/kernel/respond_to_spec.rb +0 -0
  66. data/spec/{rubyspec/core → opal}/kernel/sprintf_spec.rb +0 -0
  67. data/spec/{rubyspec/core → opal}/kernel/to_json_spec.rb +0 -0
  68. data/spec/{rubyspec/core → opal}/module/alias_method_spec.rb +0 -0
  69. data/spec/{rubyspec/core → opal}/module/ancestors_spec.rb +0 -0
  70. data/spec/{rubyspec/core → opal}/module/append_features_spec.rb +0 -0
  71. data/spec/{rubyspec/core → opal}/module/constants_spec.rb +0 -0
  72. data/spec/{rubyspec/core → opal}/module/module_function_spec.rb +0 -1
  73. data/spec/opal/native_spec.rb +85 -3
  74. data/spec/opal/numeric/equal_spec.rb +9 -0
  75. data/spec/opal/parser/irb_spec.rb +43 -0
  76. data/spec/{rubyspec/core → opal}/proc/proc_tricks_spec.rb +0 -0
  77. data/spec/opal/runtime/block_send_spec.rb +28 -0
  78. data/spec/{rubyspec/core/runtime → opal/runtime2}/call_spec.rb +0 -0
  79. data/spec/{rubyspec/core/runtime → opal/runtime2}/class_hierarchy_spec.rb +0 -0
  80. data/spec/{rubyspec/core/runtime → opal/runtime2}/def_spec.rb +0 -0
  81. data/spec/{rubyspec/core/runtime → opal/runtime2}/defined_spec.rb +0 -0
  82. data/spec/{rubyspec/core/runtime → opal/runtime2}/super_spec.rb +0 -0
  83. data/spec/opal/source_map_spec.rb +19 -0
  84. data/spec/opal/string/freeze_spec.rb +15 -0
  85. data/spec/{rubyspec/core → opal}/string/to_json_spec.rb +0 -0
  86. data/spec/ospec/runner.rb +3 -0
  87. data/spec/parser/str_spec.rb +4 -0
  88. data/spec/rubyspec/core/enumerable/fixtures/classes.rb +2 -2
  89. data/spec/rubyspec/core/enumerable/none_spec.rb +68 -0
  90. data/spec/rubyspec/core/enumerable/sort_by_spec.rb +31 -0
  91. data/spec/rubyspec/core/hash/size_spec.rb +1 -1
  92. data/spec/rubyspec/core/hash/to_native_spec.rb +3 -3
  93. data/spec/rubyspec/core/string/fixtures/classes.rb +49 -0
  94. data/spec/rubyspec/core/string/index_spec.rb +405 -0
  95. data/spec/rubyspec/filters/bugs/language/class.rb +0 -2
  96. data/spec/rubyspec/filters/bugs/language/module.rb +3 -0
  97. data/spec/rubyspec/language/array_spec.rb +1 -1
  98. data/spec/rubyspec/language/block_spec.rb +1 -1
  99. data/spec/rubyspec/language/module_spec.rb +5 -5
  100. data/spec/rubyspec/language/predefined_spec.rb +1 -2
  101. data/spec/rubyspec/library/stringscanner/element_reference_spec.rb +29 -0
  102. data/spec/rubyspec/spec_helper.rb +31 -0
  103. metadata +130 -76
  104. data/lib/opal/erb.rb +0 -41
  105. data/opal/erb.rb +0 -19
  106. data/spec/opal/erb/erb_spec.rb +0 -31
  107. data/spec/simple_erb_template.opalerb +0 -1
  108. data/spec/templates/foo/bar.opalerb +0 -1
  109. data/spec/templates/prefixed.opalerb +0 -1
@@ -3,7 +3,6 @@ language: ruby
3
3
  rvm:
4
4
  - 1.8.7
5
5
  - 1.9.3
6
- - 2.0.0
7
6
 
8
7
  notifications:
9
8
  irc: "irc.freenode.org#opal"
@@ -1,3 +1,55 @@
1
+ ## 0.4.0 2013-06-15
2
+
3
+ * Added fragments to parser. All parser methods now generate one or
4
+ more Fragments which store the original sexp. This allows us to
5
+ enumerate over them after parsing to map generated lines back to
6
+ original line numbers.
7
+
8
+ * Reverted `null` for `nil`. Too buggy at this time.
9
+
10
+ * Add Opal::SprocketsParser as Parser subclass for handling parsing
11
+ for sprockets environment. This subclass handles require statements
12
+ and stores them for sprockets to use.
13
+
14
+ * Add :irb option to parser to keep top level lvars stored inside
15
+ opal runtime so that an irb session can be persisted and maintain
16
+ access to local variables.
17
+
18
+ * Add Opal::Environment#use_gem() helper to add a gem to opals load
19
+ path.
20
+
21
+ * Stop pre-setting ivars to `nil`. This is no longer needed as `nil`
22
+ is now `null` or `undefined`.
23
+
24
+ * Use `null` as `nil` in opal. This allows us to send methods to
25
+ `null` and `undefined`, and both act as `nil`. This makes opal a
26
+ much better javascript citizen. **REVERTED**
27
+
28
+ * Add Enumerable#none? with specs.
29
+
30
+ * Add Opal.block_send() runtime helper for sending methods to an
31
+ object which uses a block.
32
+
33
+ * Remove \_klass variable for denoting ruby classes, and use
34
+ constructor instead. constructor is a javascript property used for
35
+ the same purpose, and this makes opal fit in as a better js citizen.
36
+
37
+ * Add Class.bridge\_class method to bridge a native constructor into an
38
+ opal class which will set it up with all methods from Object, as
39
+ well as giving it a scope and name.
40
+
41
+ * Added native #[]= and #to_h methods, for setting properties and
42
+ converting to a hash respectivaly.
43
+
44
+ * Fix bug where '::' was parsed as :colon2 instead of :colon3 when in
45
+ an args scope. Fixes #213
46
+
47
+ * Remove lots of properties added to opal classes. This makes normal
48
+ js constructors a lot closer to opal classes, making is easier to
49
+ treat js classes as opal classes.
50
+
51
+ * Merge Hash.from_native into Hash.new
52
+
1
53
  ## 0.3.44 2013-05-31
2
54
 
3
55
  * Cleanup runtime, and remove various flags and functions from opal
data/README.md CHANGED
@@ -41,9 +41,9 @@ javascript. These are built using `rake`, as above.
41
41
 
42
42
  ### spec
43
43
 
44
- * **core** contains rubyspecs that apply to opal.
45
- * **language** applicable specs from rubyspec for testing language semantics
46
- * **grammar** specs for opal lib (parser, lexer, grammar etc)
44
+ * **rubyspec** contains rubyspecs that apply to opal (core + language)
45
+ * **opal** opal additions/special behaviour in the runtime/corelib
46
+ * **parser** specs for opal lib (parser, lexer, grammar etc)
47
47
 
48
48
  ## License
49
49
 
data/Rakefile CHANGED
@@ -13,7 +13,7 @@ class RunSpec
13
13
  server = fork do
14
14
  serv = Opal::Server.new { |s|
15
15
  s.append_path 'spec' # before mspec, so we use our overrides
16
- s.append_path File.join(Gem::Specification.find_by_name('mspec').gem_dir, 'lib')
16
+ s.use_gem 'mspec'
17
17
  s.debug = false
18
18
  s.main = 'ospec/main'
19
19
  }
@@ -25,10 +25,11 @@ class RunSpec
25
25
  system "phantomjs \"spec/ospec/sprockets.js\" \"http://localhost:9999/\""
26
26
  success = $?.success?
27
27
 
28
+ exit 1 unless success
29
+
30
+ ensure
28
31
  Process.kill(:SIGINT, server)
29
32
  Process.wait
30
-
31
- exit 1 unless success
32
33
  end
33
34
  end
34
35
 
@@ -37,16 +38,39 @@ task :default do
37
38
  RunSpec.new
38
39
  end
39
40
 
41
+ desc "Build specs to build/specs.js and build/specs.min.js"
42
+ task :build_specs do
43
+ require 'uglifier'
44
+
45
+ Opal::Processor.arity_check_enabled = true
46
+ ENV['OPAL_SPEC'] = ["#{Dir.pwd}/spec/"].join(',')
47
+
48
+ env = Opal::Environment.new
49
+ env.append_path 'spec'
50
+ env.use_gem 'mspec'
51
+
52
+ FileUtils.mkdir_p 'build'
53
+
54
+ puts " * build/specs.js"
55
+ specs = env['ospec/main'].to_s
56
+
57
+ # puts " * build/specs.min.js"
58
+ # min = Uglifier.compile(specs)
59
+
60
+ File.open('build/specs.js', 'w+') { |o| o << specs }
61
+ # File.open('build/specs.min.js', 'w+') { |o| o << min }
62
+ end
63
+
40
64
  desc "Run task with spec:dir:file helper"
41
65
  namespace :spec do
42
66
  task 'dirs' do
43
67
  end
44
- rule '' do |t|
68
+ rule '' do |task|
45
69
 
46
70
  #build path for spec files\dirs.
47
71
  #Example:
48
72
  #spec:core => spec/core/
49
- #spec:core:array:allocae => spec/core/array/allocate_spec.rb
73
+ #spec:core:array:allocate => spec/core/array/allocate_spec.rb
50
74
  def path(dirs)
51
75
  path = "#{Dir.pwd}"
52
76
  dirs.each do |dir|
@@ -58,11 +82,11 @@ namespace :spec do
58
82
  end
59
83
  end
60
84
  path = [path].flatten
61
- raise "File or Dir with task #{t.name} not found." if path.empty?
85
+ raise ArgumentError, "File or Dir with task #{dirs.join('/')} not found." if path.empty?
62
86
  path
63
87
  end
64
88
 
65
- RunSpec.new(path(t.name.split(":")))
89
+ RunSpec.new(path(task.name.split(":")))
66
90
  end
67
91
  end
68
92
 
@@ -104,7 +128,7 @@ end
104
128
 
105
129
  # Used for uglifying source to minify
106
130
  def uglify(str)
107
- IO.popen('uglifyjs --no-mangle --compress warnings=false', 'r+') do |i|
131
+ IO.popen('uglifyjs', 'r+') do |i|
108
132
  i.puts str
109
133
  i.close_write
110
134
  return i.read
data/bin/opal CHANGED
@@ -1,33 +1,86 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'optparse'
4
- require 'opal'
5
4
 
6
5
  options = {}
7
6
  parser = OptionParser.new do |opts|
8
- opts.banner = "Usage: opal [options] file.rb"
7
+ opts.banner = 'Usage: opal [options] -- [programfile]'
9
8
 
10
- opts.on("-v", "--version", "Opal Version") do |v|
11
- puts Opal::VERSION
9
+ opts.on('-v', '--version', 'Display Opal Version') do |v|
10
+ require 'opal/version'
11
+ puts "Opal v#{Opal::VERSION}"
12
12
  exit
13
13
  end
14
14
 
15
- opts.on("-s", "--sexp", "Show Sexps") do
15
+ opts.on("-h", "--help", "Show this message") do
16
+ puts opts
17
+ exit
18
+ end
19
+
20
+ opts.separator ''
21
+ opts.separator 'Basic Options:'
22
+
23
+ opts.on('-I', '--include DIR',
24
+ 'Append a load path (may be used more than once)') do |i|
25
+ options[:load_paths] ||= []
26
+ options[:load_paths] << i
27
+ end
28
+
29
+ opts.on('-e', '--eval SOURCE', String,
30
+ 'One line of script. Several -e\'s allowed. Omit [programfile]') do |source|
31
+ options[:evals] ||= []
32
+ options[:evals] << source
33
+ end
34
+
35
+ opts.on('-s', '--sexp', 'Show Sexps') do
16
36
  options[:sexp] = true
17
37
  end
18
- end
19
38
 
20
- parser.parse!
39
+ opts.on('-c', '--compile', 'Compile to JavaScript') do
40
+ options[:compile] = true
41
+ end
42
+
43
+ opts.on('-s', '--server [PORT]', 'Start a server (default port: 3000)') do |port|
44
+ options[:server] = port.to_i
45
+ end
46
+
47
+
48
+ opts.separator ''
49
+ opts.separator 'Compilation Options:'
21
50
 
22
- if ARGV.empty?
23
- puts parser.banner
24
- else
25
- src = ARGV.first
26
- src = File.read src if File.exist? src
51
+ opts.on('-M', '--no-method-missing', 'Disable method missing') do |value|
52
+ options[:method_missing_enabled] = false
53
+ end
54
+
55
+ opts.on('-O', '--no-optimized-operators', 'Disable optimized operators') do |value|
56
+ options[:optimized_operators_enabled] = false
57
+ end
58
+
59
+ opts.on('-A', '--arity-check', 'Enable arity check') do |value|
60
+ options[:arity_check] = true
61
+ end
62
+
63
+ opts.on('-C', '--no-const-missing', 'Disable const missing') do |value|
64
+ options[:const_missing_enabled] = false
65
+ end
27
66
 
28
- if options[:sexp]
29
- puts Opal::Grammar.new.parse(src).inspect
30
- else
31
- puts Opal.parse(src)
67
+ dynamic_require_levels = %w[error warning ignore]
68
+ opts.on('-D', '--dynamic-require LEVEL', dynamic_require_levels,
69
+ 'Set levelDynamic require severity') do |level|
70
+ options[:dynamic_require_severity] = level
32
71
  end
72
+
73
+ opts.on('-P', '--no-source-map', 'Disable source map') do |value|
74
+ options[:source_map_enabled] = false
75
+ end
76
+
77
+ opts.on("--irb", "IRB var mode") do |i|
78
+ options[:irb] = true
79
+ end
80
+
33
81
  end
82
+
83
+ parser.parse!
84
+
85
+ require 'opal/cli'
86
+ Opal::CLI.new ARGV.first, options
data/config.ru CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'bundler'
2
2
  Bundler.require
3
3
 
4
- require 'opal-sprockets'
4
+ ENV['OPAL_SPEC'] = ["#{Dir.pwd}/spec/"].join(',')
5
5
 
6
6
  run Opal::Server.new { |s|
7
7
  Opal::Processor.arity_check_enabled = true
@@ -1,21 +1,41 @@
1
1
  require 'opal'
2
2
 
3
- $window.addEventListener 'DOMContentLoaded', proc {
3
+ # We can treat native objects (in this case `window`) as a ruby object
4
+ # and open up a singleton class on it and define methods on the object
5
+ # directly. This basically defines just a single ruby method onto
6
+ # `window`.
7
+ class << $global
8
+
9
+ # on_ready is a simple method that just adds a 'DOMContentLoaded'
10
+ # event onto window. `self` inside this method will be `window`,
11
+ # so we can call addEventListener as we would in ruby
12
+ def on_ready(&block)
13
+ addEventListener 'DOMContentLoaded', block, false
14
+ end
15
+ end
4
16
 
17
+ # Call our new method on window (which is accessed by `$global`
18
+ $global.on_ready do
5
19
  css = <<-CSS
6
20
  body {
7
21
  font-family: 'Arial';
8
22
  }
23
+
24
+ h1 {
25
+ color: rgb(10, 94, 232);
26
+ }
9
27
  CSS
10
28
 
11
- title = $document.createElement 'h1'
29
+ document = $global.document
30
+
31
+ title = document.createElement 'h1'
12
32
  title.className = 'main-title'
13
33
  title.innerHTML = 'Opal Native Example'
14
34
 
15
- desc = $document.createElement 'p'
35
+ desc = document.createElement 'p'
16
36
  desc.innerHTML = "Hello world! From Opal."
17
37
 
18
- target = $document.getElementById 'native-example'
38
+ target = document.getElementById 'native-example'
19
39
 
20
40
  unless target
21
41
  raise "'native-example' doesn't exist?"
@@ -24,15 +44,14 @@ $window.addEventListener 'DOMContentLoaded', proc {
24
44
  target.appendChild title
25
45
  target.appendChild desc
26
46
 
27
- styles = $document.createElement 'style'
47
+ styles = document.createElement 'style'
28
48
  styles.type = 'text/css'
29
49
 
30
50
  if styles.respond_to? :styleSheet
31
51
  styles.styleSheet.cssText = css
32
52
  else
33
- styles.appendChild $document.createTextNode css
53
+ styles.appendChild document.createTextNode css
34
54
  end
35
55
 
36
- $document.getElementsByTagName('head')[0].appendChild(styles)
37
-
38
- }, false
56
+ document.getElementsByTagName('head')[0].appendChild(styles)
57
+ end
@@ -1,5 +1,5 @@
1
1
  require 'opal'
2
2
 
3
3
  # use native alert from browser
4
- Native.global.alert "Boo! From opal."
4
+ $global.alert "Boo! from opal"
5
5
 
@@ -1,6 +1,5 @@
1
1
  require 'opal/parser'
2
2
  require 'opal/processor'
3
- require 'opal/erb'
4
3
  require 'opal/server'
5
4
  require 'opal/version'
6
5
 
@@ -0,0 +1,106 @@
1
+ require 'opal'
2
+
3
+ module Opal
4
+ class CLI
5
+ attr_reader :options, :filename
6
+
7
+ def initialize _filename, options
8
+ @options = options
9
+ @filename = _filename
10
+
11
+ processor_options.each do |option|
12
+ key = option.to_sym
13
+ next unless options.has_key? key
14
+ Opal::Processor.send("#{option}=", options[key])
15
+ end
16
+
17
+ if options[:evals] and options[:evals].any?
18
+ require 'tempfile'
19
+ path = File.join(Dir.tmpdir,"opal-#{$$}.js.rb")
20
+ File.open(path, 'w') do |tempfile|
21
+ options[:load_paths] ||= []
22
+ options[:load_paths] << File.dirname(path)
23
+
24
+ options[:evals].each do |code|
25
+ tempfile.puts 'require "opal"'
26
+ tempfile.puts code
27
+ end
28
+ end
29
+ @filename = File.basename(path)
30
+ end
31
+
32
+ case
33
+ when options[:sexp]
34
+ puts sexp.inspect
35
+ when options[:compile]
36
+ if File.exist?(filename)
37
+ puts sprockets[filename].to_a.last
38
+ else
39
+ puts Opal.parse(filename, options)
40
+ end
41
+ when options[:server]
42
+ server_start
43
+ else
44
+ run
45
+ end
46
+ end
47
+
48
+ def run
49
+ begin
50
+ full_source = sprockets[filename]
51
+ IO.popen('node', 'w') do |stdin|
52
+ stdin.write full_source
53
+ end
54
+ rescue Errno::ENOENT
55
+ $stderr.puts 'Please install Node.js to be able to run Opal scripts.'
56
+ exit 127
57
+ end
58
+ end
59
+
60
+ def sexp
61
+ Opal::Grammar.new.parse(source)
62
+ end
63
+
64
+ def source
65
+ File.exist?(filename) ? File.read(filename) : filename
66
+ end
67
+
68
+ def processor_options
69
+ %w[
70
+ method_missing_enabled
71
+ optimized_operators_enabled
72
+ arity_check_enabled
73
+ const_missing_enabled
74
+ dynamic_require_severity
75
+ source_map_enabled
76
+ irb_enabled
77
+ ]
78
+ end
79
+
80
+ def sprockets
81
+ server.sprockets
82
+ end
83
+
84
+ def server
85
+ @server ||= Opal::Server.new do |s|
86
+ (options[:load_paths] || []).each do |path|
87
+ s.append_path path
88
+ end
89
+ s.main = File.basename(filename, '.rb')
90
+ end
91
+ end
92
+
93
+ def server_start
94
+ require 'rack'
95
+ require 'webrick'
96
+ require 'logger'
97
+
98
+ Rack::Server.start(
99
+ :app => server,
100
+ :Port => options[:port] || 3000,
101
+ :AccessLog => [],
102
+ :Logger => Logger.new($stdout)
103
+ )
104
+ end
105
+ end
106
+ end