opal 0.3.44 → 0.4.0

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 (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