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.
- data/.travis.yml +0 -1
- data/CHANGELOG.md +52 -0
- data/README.md +3 -3
- data/Rakefile +32 -8
- data/bin/opal +69 -16
- data/config.ru +1 -1
- data/examples/native/app/app.rb +28 -9
- data/examples/rack/app/app.rb +1 -1
- data/lib/opal.rb +0 -1
- data/lib/opal/cli.rb +106 -0
- data/lib/opal/lexer.rb +4 -2
- data/lib/opal/parser.rb +603 -360
- data/lib/opal/processor.rb +20 -8
- data/lib/opal/server.rb +47 -0
- data/lib/opal/source_map.rb +63 -0
- data/lib/opal/sprockets_parser.rb +77 -0
- data/lib/opal/sprockets_source_map_header.rb +21 -0
- data/lib/opal/target_scope.rb +14 -7
- data/lib/opal/version.rb +1 -1
- data/opal.gemspec +2 -0
- data/opal/opal-browser/script_loader.rb +7 -7
- data/opal/opal-parser.js.erb +2 -2
- data/opal/opal-source-maps.js.erb +2 -0
- data/opal/opal.rb +3 -4
- data/opal/opal/array.rb +31 -28
- data/opal/opal/boolean.rb +4 -0
- data/opal/opal/class.rb +14 -5
- data/opal/opal/enumerable.rb +68 -8
- data/opal/opal/error.rb +1 -1
- data/opal/opal/hash.rb +15 -18
- data/opal/opal/kernel.rb +24 -10
- data/opal/opal/native.rb +31 -0
- data/opal/opal/nil_class.rb +7 -2
- data/opal/opal/numeric.rb +10 -1
- data/opal/opal/proc.rb +4 -0
- data/opal/opal/range.rb +1 -1
- data/opal/opal/regexp.rb +13 -3
- data/opal/opal/runtime.js +134 -51
- data/opal/opal/string.rb +45 -22
- data/opal/opal/time.rb +25 -7
- data/opal/source_map.rb +63 -0
- data/opal/source_map/generator.rb +251 -0
- data/opal/source_map/parser.rb +102 -0
- data/opal/source_map/vlq.rb +122 -0
- data/opal/strscan.rb +30 -12
- data/spec/opal/class/_inherited_spec.rb +1 -1
- data/spec/{rubyspec/core → opal}/class/bridge_class_spec.rb +5 -3
- data/spec/{rubyspec/core → opal}/class/extend_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/class/instance_methods_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/class/last_value_spec.rb +0 -1
- data/spec/{rubyspec/core → opal}/json/parse_spec.rb +0 -0
- data/spec/{rubyspec/core/kernel/block_given.rb → opal/kernel/block_given_spec.rb} +0 -0
- data/spec/{rubyspec/core → opal}/kernel/class_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/extend_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/format_spec.rb +0 -0
- data/spec/opal/kernel/freeze_spec.rb +15 -0
- data/spec/{rubyspec/core → opal}/kernel/match_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/method_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/methods_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/nil_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/p_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/printf_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/proc_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/rand_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/respond_to_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/sprintf_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/to_json_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/module/alias_method_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/module/ancestors_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/module/append_features_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/module/constants_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/module/module_function_spec.rb +0 -1
- data/spec/opal/native_spec.rb +85 -3
- data/spec/opal/numeric/equal_spec.rb +9 -0
- data/spec/opal/parser/irb_spec.rb +43 -0
- data/spec/{rubyspec/core → opal}/proc/proc_tricks_spec.rb +0 -0
- data/spec/opal/runtime/block_send_spec.rb +28 -0
- data/spec/{rubyspec/core/runtime → opal/runtime2}/call_spec.rb +0 -0
- data/spec/{rubyspec/core/runtime → opal/runtime2}/class_hierarchy_spec.rb +0 -0
- data/spec/{rubyspec/core/runtime → opal/runtime2}/def_spec.rb +0 -0
- data/spec/{rubyspec/core/runtime → opal/runtime2}/defined_spec.rb +0 -0
- data/spec/{rubyspec/core/runtime → opal/runtime2}/super_spec.rb +0 -0
- data/spec/opal/source_map_spec.rb +19 -0
- data/spec/opal/string/freeze_spec.rb +15 -0
- data/spec/{rubyspec/core → opal}/string/to_json_spec.rb +0 -0
- data/spec/ospec/runner.rb +3 -0
- data/spec/parser/str_spec.rb +4 -0
- data/spec/rubyspec/core/enumerable/fixtures/classes.rb +2 -2
- data/spec/rubyspec/core/enumerable/none_spec.rb +68 -0
- data/spec/rubyspec/core/enumerable/sort_by_spec.rb +31 -0
- data/spec/rubyspec/core/hash/size_spec.rb +1 -1
- data/spec/rubyspec/core/hash/to_native_spec.rb +3 -3
- data/spec/rubyspec/core/string/fixtures/classes.rb +49 -0
- data/spec/rubyspec/core/string/index_spec.rb +405 -0
- data/spec/rubyspec/filters/bugs/language/class.rb +0 -2
- data/spec/rubyspec/filters/bugs/language/module.rb +3 -0
- data/spec/rubyspec/language/array_spec.rb +1 -1
- data/spec/rubyspec/language/block_spec.rb +1 -1
- data/spec/rubyspec/language/module_spec.rb +5 -5
- data/spec/rubyspec/language/predefined_spec.rb +1 -2
- data/spec/rubyspec/library/stringscanner/element_reference_spec.rb +29 -0
- data/spec/rubyspec/spec_helper.rb +31 -0
- metadata +130 -76
- data/lib/opal/erb.rb +0 -41
- data/opal/erb.rb +0 -19
- data/spec/opal/erb/erb_spec.rb +0 -31
- data/spec/simple_erb_template.opalerb +0 -1
- data/spec/templates/foo/bar.opalerb +0 -1
- data/spec/templates/prefixed.opalerb +0 -1
data/lib/opal/processor.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'sprockets'
|
|
2
|
+
require 'opal/sprockets_parser'
|
|
2
3
|
|
|
3
4
|
module Opal
|
|
4
5
|
# Proccess using Sprockets
|
|
@@ -13,9 +14,13 @@ module Opal
|
|
|
13
14
|
# ruby source file to build. There are some options you can override globally
|
|
14
15
|
# which effect how certain ruby features are handled:
|
|
15
16
|
#
|
|
16
|
-
# * method_missing_enabled
|
|
17
|
+
# * method_missing_enabled [true by default]
|
|
17
18
|
# * optimized_operators_enabled [true by default]
|
|
18
|
-
# * arity_check_enabled
|
|
19
|
+
# * arity_check_enabled [false by default]
|
|
20
|
+
# * const_missing_enabled [true by default]
|
|
21
|
+
# * dynamic_require_severity [true by default]
|
|
22
|
+
# * source_map_enabled [true by default]
|
|
23
|
+
# * irb_enabled [false by default]
|
|
19
24
|
#
|
|
20
25
|
class Processor < Tilt::Template
|
|
21
26
|
self.default_mime_type = 'application/javascript'
|
|
@@ -30,13 +35,17 @@ module Opal
|
|
|
30
35
|
attr_accessor :arity_check_enabled
|
|
31
36
|
attr_accessor :const_missing_enabled
|
|
32
37
|
attr_accessor :dynamic_require_severity
|
|
38
|
+
attr_accessor :source_map_enabled
|
|
39
|
+
attr_accessor :irb_enabled
|
|
33
40
|
end
|
|
34
41
|
|
|
35
|
-
self.method_missing_enabled
|
|
42
|
+
self.method_missing_enabled = true
|
|
36
43
|
self.optimized_operators_enabled = true
|
|
37
|
-
self.arity_check_enabled
|
|
38
|
-
self.const_missing_enabled
|
|
39
|
-
self.dynamic_require_severity
|
|
44
|
+
self.arity_check_enabled = false
|
|
45
|
+
self.const_missing_enabled = true
|
|
46
|
+
self.dynamic_require_severity = :error # :error, :warning or :ignore
|
|
47
|
+
self.source_map_enabled = true
|
|
48
|
+
self.irb_enabled = false
|
|
40
49
|
|
|
41
50
|
def initialize_engine
|
|
42
51
|
require_template_library 'opal'
|
|
@@ -52,10 +61,13 @@ module Opal
|
|
|
52
61
|
:arity_check => self.class.arity_check_enabled,
|
|
53
62
|
:const_missing => self.class.const_missing_enabled,
|
|
54
63
|
:dynamic_require_severity => self.class.dynamic_require_severity,
|
|
55
|
-
:
|
|
64
|
+
:source_map_enabled => self.class.source_map_enabled,
|
|
65
|
+
:irb => self.class.irb_enabled,
|
|
66
|
+
:file => context.logical_path,
|
|
67
|
+
:source_file => context.pathname.to_s,
|
|
56
68
|
}
|
|
57
69
|
|
|
58
|
-
parser = Opal::
|
|
70
|
+
parser = Opal::SprocketsParser.new
|
|
59
71
|
result = parser.parse data, options
|
|
60
72
|
|
|
61
73
|
parser.requires.each { |r| context.require_asset r }
|
data/lib/opal/server.rb
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
require 'erb'
|
|
2
|
+
require 'rack'
|
|
3
|
+
require 'rack/showexceptions'
|
|
4
|
+
require 'opal/sprockets_source_map_header'
|
|
5
|
+
require 'opal/source_map'
|
|
2
6
|
|
|
3
7
|
module Opal
|
|
4
8
|
class Environment < ::Sprockets::Environment
|
|
@@ -6,6 +10,39 @@ module Opal
|
|
|
6
10
|
super
|
|
7
11
|
Opal.paths.each { |p| append_path p }
|
|
8
12
|
end
|
|
13
|
+
|
|
14
|
+
def use_gem gem_name
|
|
15
|
+
append_path File.join(Gem::Specification.find_by_name(gem_name).gem_dir, 'lib')
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class SourceMapServer
|
|
20
|
+
def initialize sprockets
|
|
21
|
+
@sprockets = sprockets
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
attr_reader :sprockets
|
|
25
|
+
|
|
26
|
+
attr_writer :prefix
|
|
27
|
+
|
|
28
|
+
def prefix
|
|
29
|
+
@prefix ||= '/__opal_source_maps__'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def inspect
|
|
33
|
+
"#<#{self.class}:#{object_id}>"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def call(env)
|
|
37
|
+
path = env['PATH_INFO'].gsub(/^\/|\.js\.map$/, '')
|
|
38
|
+
asset = sprockets[path]
|
|
39
|
+
return [404, {}, []] if asset.nil?
|
|
40
|
+
|
|
41
|
+
source = asset.to_s
|
|
42
|
+
map = Opal::SourceMap.new(source, asset.pathname.to_s)
|
|
43
|
+
|
|
44
|
+
return [200, {"Content-Type" => "text/json"}, [map.to_s]]
|
|
45
|
+
end
|
|
9
46
|
end
|
|
10
47
|
|
|
11
48
|
class Server
|
|
@@ -25,16 +62,26 @@ module Opal
|
|
|
25
62
|
@sprockets.append_path path
|
|
26
63
|
end
|
|
27
64
|
|
|
65
|
+
def use_gem gem_name
|
|
66
|
+
@sprockets.use_gem gem_name
|
|
67
|
+
end
|
|
68
|
+
|
|
28
69
|
def create_app
|
|
29
70
|
server, sprockets = self, @sprockets
|
|
30
71
|
|
|
31
72
|
@app = Rack::Builder.app do
|
|
73
|
+
use Rack::ShowExceptions
|
|
32
74
|
map('/assets') { run sprockets }
|
|
75
|
+
map(server.source_maps.prefix) { run server.source_maps }
|
|
33
76
|
use Index, server
|
|
34
77
|
run Rack::Directory.new(server.public_dir)
|
|
35
78
|
end
|
|
36
79
|
end
|
|
37
80
|
|
|
81
|
+
def source_maps
|
|
82
|
+
@source_maps ||= SourceMapServer.new(@sprockets)
|
|
83
|
+
end
|
|
84
|
+
|
|
38
85
|
def call(env)
|
|
39
86
|
@app.call env
|
|
40
87
|
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require 'opal'
|
|
2
|
+
require 'source_map'
|
|
3
|
+
|
|
4
|
+
module Opal
|
|
5
|
+
class SourceMap
|
|
6
|
+
LINE_REGEXP = %r{/\*:(\d+)\*/}.freeze
|
|
7
|
+
FILE_REGEXP = %r{/\*-file:(.+?)-\*/}.freeze
|
|
8
|
+
|
|
9
|
+
attr_reader :generated, :file
|
|
10
|
+
|
|
11
|
+
def initialize generated, file
|
|
12
|
+
@generated = generated
|
|
13
|
+
@file = file
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def map
|
|
17
|
+
@map ||= ::SourceMap.new.tap do |map|
|
|
18
|
+
source_file = file
|
|
19
|
+
generated.lines.each_with_index do |line, index|
|
|
20
|
+
generated_line = index+1
|
|
21
|
+
if line =~ FILE_REGEXP
|
|
22
|
+
source_file = "file://#{$1}"
|
|
23
|
+
map.add_mapping(
|
|
24
|
+
:generated_line => generated_line,
|
|
25
|
+
:generated_col => 0,
|
|
26
|
+
:source_line => 1,
|
|
27
|
+
:source_col => 0,
|
|
28
|
+
:source => source_file
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
pos = 0
|
|
33
|
+
while (pos = line.index(LINE_REGEXP, pos))
|
|
34
|
+
pos += $~.size
|
|
35
|
+
source_line = $1.to_i + 1
|
|
36
|
+
source_col = 0 # until column info will be available
|
|
37
|
+
generated_col = pos
|
|
38
|
+
map.add_mapping(
|
|
39
|
+
:generated_line => generated_line,
|
|
40
|
+
:generated_col => generated_col,
|
|
41
|
+
:source_line => source_line,
|
|
42
|
+
:source_col => source_col,
|
|
43
|
+
:source => source_file
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def as_json
|
|
51
|
+
map.as_json
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def to_s
|
|
55
|
+
map.to_s
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def magic_comment map_path
|
|
59
|
+
"\n//@ sourceMappingURL=file://#{map_path}"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
require 'opal/parser'
|
|
2
|
+
|
|
3
|
+
module Opal
|
|
4
|
+
class SprocketsParser < Parser
|
|
5
|
+
|
|
6
|
+
def self.parse source, options = {}
|
|
7
|
+
self.new.parse source, options
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Holds an array of paths which this file 'requires'.
|
|
11
|
+
# @return Array<String>
|
|
12
|
+
attr_reader :requires
|
|
13
|
+
|
|
14
|
+
def parse source, options = {}
|
|
15
|
+
@requires = []
|
|
16
|
+
@dynamic_require_severity = (options[:dynamic_require_severity] || :error)
|
|
17
|
+
super source, options
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def process_call sexp, level
|
|
21
|
+
if sexp[1] == :require
|
|
22
|
+
return handle_require sexp[2][1]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
super sexp, level
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def handle_require(sexp)
|
|
29
|
+
str = handle_require_sexp sexp
|
|
30
|
+
@requires << str unless str.nil? if @requires
|
|
31
|
+
fragment("", sexp)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def handle_require_sexp(sexp)
|
|
35
|
+
type = sexp.shift
|
|
36
|
+
|
|
37
|
+
if type == :str
|
|
38
|
+
return sexp[0]
|
|
39
|
+
elsif type == :call
|
|
40
|
+
recv, meth, args = sexp
|
|
41
|
+
parts = args[1..-1].map { |s| handle_require_sexp s }
|
|
42
|
+
|
|
43
|
+
if recv == [:const, :File]
|
|
44
|
+
if meth == :expand_path
|
|
45
|
+
return handle_expand_path(*parts)
|
|
46
|
+
elsif meth == :join
|
|
47
|
+
return handle_expand_path parts.join("/")
|
|
48
|
+
elsif meth == :dirname
|
|
49
|
+
return handle_expand_path parts[0].split("/")[0...-1].join("/")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
case @dynamic_require_severity
|
|
56
|
+
when :error
|
|
57
|
+
error "Cannot handle dynamic require"
|
|
58
|
+
when :warning
|
|
59
|
+
warning "Cannot handle dynamic require"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def handle_expand_path(path, base = '')
|
|
64
|
+
"#{base}/#{path}".split("/").inject([]) do |p, part|
|
|
65
|
+
if part == ''
|
|
66
|
+
# we had '//', so ignore
|
|
67
|
+
elsif part == '..'
|
|
68
|
+
p.pop
|
|
69
|
+
else
|
|
70
|
+
p << part
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
p
|
|
74
|
+
end.join "/"
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'sprockets/server'
|
|
2
|
+
|
|
3
|
+
module Sprockets
|
|
4
|
+
module Server
|
|
5
|
+
|
|
6
|
+
# Adds the source map header to all sprocket responses for assets
|
|
7
|
+
# with a .rb or .opal extension in the extension chain.
|
|
8
|
+
def headers_with_opal_source_maps(env, asset, length)
|
|
9
|
+
headers_without_opal_source_maps(env, asset, length).tap do |headers|
|
|
10
|
+
if asset.pathname.to_s =~ /\.(rb|opal)\b/
|
|
11
|
+
headers['X-SourceMap'] = '/__opal_source_maps__/'+asset.logical_path + '.map'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Poor man's alias_method_chain :)
|
|
17
|
+
alias headers_without_opal_source_maps headers
|
|
18
|
+
alias headers headers_with_opal_source_maps
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/opal/target_scope.rb
CHANGED
|
@@ -113,12 +113,12 @@ module Opal
|
|
|
113
113
|
##
|
|
114
114
|
# Vars to use inside each scope
|
|
115
115
|
def to_vars
|
|
116
|
-
vars = @
|
|
117
|
-
vars.push(*@
|
|
116
|
+
vars = @temps.dup
|
|
117
|
+
vars.push(*@locals.map { |l| "#{l} = nil" })
|
|
118
118
|
current_self = @parser.current_self
|
|
119
119
|
|
|
120
120
|
iv = ivars.map do |ivar|
|
|
121
|
-
|
|
121
|
+
"if (#{current_self}#{ivar} == null) #{current_self}#{ivar} = nil;\n"
|
|
122
122
|
end
|
|
123
123
|
|
|
124
124
|
indent = @parser.parser_indent
|
|
@@ -126,19 +126,26 @@ module Opal
|
|
|
126
126
|
str = ivars.empty? ? res : "#{res}\n#{indent}#{iv.join indent}"
|
|
127
127
|
|
|
128
128
|
if class? and !@proto_ivars.empty?
|
|
129
|
+
#raise "FIXME to_vars"
|
|
129
130
|
pvars = @proto_ivars.map { |i| "#{proto}#{i}"}.join(' = ')
|
|
130
|
-
"%s\n%s%s = nil;" % [str, indent, pvars]
|
|
131
|
+
result = "%s\n%s%s = nil;" % [str, indent, pvars]
|
|
131
132
|
else
|
|
132
|
-
str
|
|
133
|
+
result = str
|
|
133
134
|
end
|
|
135
|
+
|
|
136
|
+
fragment(result)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def fragment(code, sexp = nil)
|
|
140
|
+
@parser.fragment code
|
|
134
141
|
end
|
|
135
142
|
|
|
136
143
|
# Generates code for this module to donate methods
|
|
137
144
|
def to_donate_methods
|
|
138
145
|
if should_donate? and !@methods.empty?
|
|
139
|
-
"%s;__opal.donate(#{@name}, [%s]);" % [@parser.parser_indent, @methods.map(&:inspect).join(', ')]
|
|
146
|
+
fragment("%s;__opal.donate(#{@name}, [%s]);" % [@parser.parser_indent, @methods.map(&:inspect).join(', ')])
|
|
140
147
|
else
|
|
141
|
-
""
|
|
148
|
+
fragment("")
|
|
142
149
|
end
|
|
143
150
|
end
|
|
144
151
|
|
data/lib/opal/version.rb
CHANGED
data/opal.gemspec
CHANGED
|
@@ -2,10 +2,10 @@ class BrowserScriptLoader
|
|
|
2
2
|
def run
|
|
3
3
|
handler = proc { find_scripts }
|
|
4
4
|
|
|
5
|
-
if $
|
|
6
|
-
$
|
|
7
|
-
|
|
8
|
-
$
|
|
5
|
+
if $global.respond_to? :addEventListener
|
|
6
|
+
$global.addEventListener 'DOMContentLoaded', handler, false
|
|
7
|
+
elsif @global.respond_to? :attachEvent
|
|
8
|
+
$global.attachEvent 'onload', handler
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
|
|
@@ -20,16 +20,16 @@ class BrowserScriptLoader
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def ruby_scripts
|
|
23
|
-
$document.getElementsByTagName('script').to_a.select { |s|
|
|
23
|
+
$global.document.getElementsByTagName('script').to_a.select { |s|
|
|
24
24
|
s.type == "text/ruby" }
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def run_ruby str
|
|
28
|
-
$
|
|
28
|
+
$global.Opal.eval str
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
if $
|
|
32
|
+
if $global.respond_to? :document
|
|
33
33
|
BrowserScriptLoader.new.run
|
|
34
34
|
end
|
|
35
35
|
|
data/opal/opal-parser.js.erb
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
<% require_asset 'strscan' %>
|
|
4
4
|
|
|
5
5
|
// We need (some) of the libs from our real ruby parser (not in sprockets load path)
|
|
6
|
-
<% %w(opal/grammar opal/lexer opal/parser opal/target_scope opal/core_ext opal/lexer_scope opal/grammar_helpers opal/parser opal).each do |f| %>
|
|
7
|
-
<%= Opal.parse File.read(File.join Opal.core_dir, '..', 'lib', "#{f}.rb") %>
|
|
6
|
+
<% %w(opal/version opal/grammar opal/lexer opal/parser opal/target_scope opal/core_ext opal/lexer_scope opal/grammar_helpers opal/parser opal).each do |f| %>
|
|
7
|
+
<%= Opal::SprocketsParser.parse File.read(File.join Opal.core_dir, '..', 'lib', "#{f}.rb") %>
|
|
8
8
|
<% end %>
|
|
9
9
|
|
|
10
10
|
Opal.eval = function(str) {
|
data/opal/opal.rb
CHANGED
|
@@ -17,6 +17,7 @@ require 'opal/proc'
|
|
|
17
17
|
require 'opal/range'
|
|
18
18
|
require 'opal/time'
|
|
19
19
|
require 'opal/json'
|
|
20
|
+
require 'opal/native'
|
|
20
21
|
|
|
21
22
|
# regexp matches
|
|
22
23
|
$& = $~ = $` = $' = nil
|
|
@@ -27,10 +28,8 @@ $: = []
|
|
|
27
28
|
# split lines
|
|
28
29
|
$/ = "\n"
|
|
29
30
|
|
|
30
|
-
# native
|
|
31
|
-
$global = `Opal.global`
|
|
32
|
-
$window = $global
|
|
33
|
-
$document = $window.document
|
|
31
|
+
# native global
|
|
32
|
+
$$ = $global = `Opal.global`
|
|
34
33
|
|
|
35
34
|
ARGV = []
|
|
36
35
|
ARGF = Object.new
|
data/opal/opal/array.rb
CHANGED
|
@@ -165,22 +165,22 @@ class Array
|
|
|
165
165
|
for (var i = 0, length = #{self}.length, tmp1, tmp2; i < length; i++) {
|
|
166
166
|
tmp1 = #{self}[i];
|
|
167
167
|
tmp2 = #{other}[i];
|
|
168
|
-
|
|
168
|
+
|
|
169
169
|
//recursive
|
|
170
|
-
if ((typeof(tmp1.indexOf) == "function") &&
|
|
171
|
-
(typeof(tmp2.indexOf) == "function") &&
|
|
170
|
+
if (tmp1 && (typeof(tmp1.indexOf) == "function") &&
|
|
171
|
+
(typeof(tmp2.indexOf) == "function") && tmp2 &&
|
|
172
172
|
(tmp1.indexOf(tmp2) == tmp2.indexOf(tmp1))) {
|
|
173
173
|
if (tmp1.indexOf(tmp1) == tmp2.indexOf(tmp2)) {
|
|
174
174
|
continue;
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
|
-
|
|
177
|
+
|
|
178
178
|
if (!#{`#{self}[i]` == `other[i]`}) {
|
|
179
179
|
return false;
|
|
180
180
|
}
|
|
181
|
-
|
|
181
|
+
|
|
182
182
|
}
|
|
183
|
-
|
|
183
|
+
|
|
184
184
|
|
|
185
185
|
return true;
|
|
186
186
|
}
|
|
@@ -285,6 +285,7 @@ class Array
|
|
|
285
285
|
%x{
|
|
286
286
|
var result = [];
|
|
287
287
|
|
|
288
|
+
|
|
288
289
|
for (var i = 0, length = #{self}.length, value; i < length; i++) {
|
|
289
290
|
if ((value = block(#{self}[i])) === __breaker) {
|
|
290
291
|
return __breaker.$v;
|
|
@@ -667,20 +668,20 @@ class Array
|
|
|
667
668
|
def last(count = undefined)
|
|
668
669
|
%x{
|
|
669
670
|
var length = #{self}.length;
|
|
670
|
-
|
|
671
|
-
if (count === nil || typeof(count) == 'string') {
|
|
671
|
+
|
|
672
|
+
if (count === nil || typeof(count) == 'string') {
|
|
672
673
|
#{ raise TypeError, "no implicit conversion to integer" };
|
|
673
674
|
}
|
|
674
|
-
|
|
675
|
+
|
|
675
676
|
if (typeof(count) == 'object') {
|
|
676
677
|
if (typeof(count['$to_int']) == 'function') {
|
|
677
678
|
count = count['$to_int']();
|
|
678
|
-
}
|
|
679
|
+
}
|
|
679
680
|
else {
|
|
680
681
|
#{ raise TypeError, "no implicit conversion to integer" };
|
|
681
682
|
}
|
|
682
683
|
}
|
|
683
|
-
|
|
684
|
+
|
|
684
685
|
if (count == null) {
|
|
685
686
|
return length === 0 ? nil : #{self}[length - 1];
|
|
686
687
|
}
|
|
@@ -783,7 +784,9 @@ class Array
|
|
|
783
784
|
`#{self}.slice(0).reverse()`
|
|
784
785
|
end
|
|
785
786
|
|
|
786
|
-
|
|
787
|
+
def reverse!
|
|
788
|
+
`#{self}.reverse()`
|
|
789
|
+
end
|
|
787
790
|
|
|
788
791
|
def reverse_each(&block)
|
|
789
792
|
reverse.each &block
|
|
@@ -856,7 +859,7 @@ class Array
|
|
|
856
859
|
|
|
857
860
|
alias size length
|
|
858
861
|
|
|
859
|
-
def shuffle
|
|
862
|
+
def shuffle
|
|
860
863
|
%x{
|
|
861
864
|
for (var i = #{self}.length - 1; i > 0; i--) {
|
|
862
865
|
var j = Math.floor(Math.random() * (i + 1));
|
|
@@ -894,7 +897,7 @@ class Array
|
|
|
894
897
|
var copy = #{self}.slice();
|
|
895
898
|
var t_arg_error = false;
|
|
896
899
|
var t_break = [];
|
|
897
|
-
|
|
900
|
+
|
|
898
901
|
if (block !== nil) {
|
|
899
902
|
var result = copy.sort(function(x, y) {
|
|
900
903
|
var result = block(x, y);
|
|
@@ -902,12 +905,12 @@ class Array
|
|
|
902
905
|
t_break.push(__breaker.$v);
|
|
903
906
|
}
|
|
904
907
|
if (result === nil) {
|
|
905
|
-
t_arg_error = true;
|
|
908
|
+
t_arg_error = true;
|
|
906
909
|
}
|
|
907
|
-
if (result['$<=>'] && typeof(result['$<=>']) == "function") {
|
|
910
|
+
if ((result != null) && result['$<=>'] && typeof(result['$<=>']) == "function") {
|
|
908
911
|
result = result['$<=>'](0);
|
|
909
912
|
}
|
|
910
|
-
if (
|
|
913
|
+
if (result !== -1 && result !== 0 && result !== 1) {
|
|
911
914
|
t_arg_error = true;
|
|
912
915
|
}
|
|
913
916
|
return result;
|
|
@@ -920,26 +923,26 @@ class Array
|
|
|
920
923
|
|
|
921
924
|
return result;
|
|
922
925
|
}
|
|
923
|
-
|
|
924
|
-
var result = copy.sort(function(a, b){
|
|
926
|
+
|
|
927
|
+
var result = copy.sort(function(a, b){
|
|
925
928
|
if (typeof(a) !== typeof(b)) {
|
|
926
929
|
t_arg_error = true;
|
|
927
930
|
}
|
|
928
|
-
|
|
931
|
+
|
|
929
932
|
if (a['$<=>'] && typeof(a['$<=>']) == "function") {
|
|
930
933
|
var result = a['$<=>'](b);
|
|
931
934
|
if (result === nil) {
|
|
932
935
|
t_arg_error = true;
|
|
933
|
-
}
|
|
934
|
-
return result;
|
|
935
|
-
}
|
|
936
|
+
}
|
|
937
|
+
return result;
|
|
938
|
+
}
|
|
936
939
|
if (a > b)
|
|
937
940
|
return 1;
|
|
938
941
|
if (a < b)
|
|
939
942
|
return -1;
|
|
940
|
-
return 0;
|
|
943
|
+
return 0;
|
|
941
944
|
});
|
|
942
|
-
|
|
945
|
+
|
|
943
946
|
if (t_arg_error)
|
|
944
947
|
#{raise ArgumentError, "Array#sort"};
|
|
945
948
|
|
|
@@ -1008,15 +1011,15 @@ class Array
|
|
|
1008
1011
|
}
|
|
1009
1012
|
end
|
|
1010
1013
|
|
|
1011
|
-
def
|
|
1014
|
+
def to_n
|
|
1012
1015
|
%x{
|
|
1013
1016
|
var result = [], obj
|
|
1014
1017
|
|
|
1015
1018
|
for (var i = 0, len = #{self}.length; i < len; i++) {
|
|
1016
1019
|
obj = #{self}[i];
|
|
1017
1020
|
|
|
1018
|
-
if (obj.$
|
|
1019
|
-
result.push(#{ `obj`.
|
|
1021
|
+
if (obj.$to_n) {
|
|
1022
|
+
result.push(#{ `obj`.to_n });
|
|
1020
1023
|
}
|
|
1021
1024
|
else {
|
|
1022
1025
|
result.push(obj);
|