opal 0.7.2 → 0.8.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -1
  3. data/CHANGELOG.md +29 -0
  4. data/CONTRIBUTING.md +51 -4
  5. data/Gemfile +3 -0
  6. data/README.md +5 -5
  7. data/config.ru +1 -1
  8. data/examples/sinatra/Gemfile +1 -0
  9. data/examples/sinatra/config.ru +13 -3
  10. data/lib/mspec/opal/rake_task.rb +21 -30
  11. data/lib/mspec/opal/runner.rb +37 -0
  12. data/lib/mspec/opal/special_calls.rb +6 -0
  13. data/lib/opal/builder.rb +1 -0
  14. data/lib/opal/builder_processors.rb +5 -2
  15. data/lib/opal/cli_runners/phantom.js +10 -1
  16. data/lib/opal/compiler.rb +6 -3
  17. data/lib/opal/config.rb +48 -0
  18. data/lib/opal/nodes/call.rb +3 -2
  19. data/lib/opal/nodes/literal.rb +19 -2
  20. data/lib/opal/parser/grammar.rb +2224 -2196
  21. data/lib/opal/parser/grammar.y +25 -7
  22. data/lib/opal/parser/lexer.rb +12 -9
  23. data/lib/opal/path_reader.rb +1 -1
  24. data/lib/opal/sprockets/erb.rb +6 -20
  25. data/lib/opal/sprockets/path_reader.rb +4 -2
  26. data/lib/opal/sprockets/processor.rb +135 -80
  27. data/lib/opal/sprockets/server.rb +49 -78
  28. data/lib/opal/sprockets/source_map_header_patch.rb +41 -0
  29. data/lib/opal/sprockets/source_map_server.rb +115 -0
  30. data/lib/opal/version.rb +1 -1
  31. data/lib/tilt/opal.rb +48 -0
  32. data/opal.gemspec +1 -1
  33. data/opal/corelib/array.rb +179 -51
  34. data/opal/corelib/array/inheritance.rb +14 -0
  35. data/opal/corelib/boolean.rb +5 -0
  36. data/opal/corelib/hash.rb +1 -1
  37. data/opal/corelib/kernel.rb +660 -164
  38. data/opal/corelib/match_data.rb +44 -21
  39. data/opal/corelib/module.rb +83 -53
  40. data/opal/corelib/numeric.rb +15 -1
  41. data/opal/corelib/regexp.rb +31 -75
  42. data/opal/corelib/runtime.js +20 -8
  43. data/opal/corelib/string.rb +754 -243
  44. data/opal/corelib/string/inheritance.rb +20 -3
  45. data/opal/corelib/struct.rb +30 -6
  46. data/opal/corelib/variables.rb +2 -2
  47. data/spec/filters/bugs/array.rb +0 -39
  48. data/spec/filters/bugs/kernel.rb +10 -7
  49. data/spec/filters/bugs/module.rb +21 -0
  50. data/spec/filters/bugs/opal.rb +0 -5
  51. data/spec/filters/bugs/singleton.rb +0 -2
  52. data/spec/filters/bugs/string.rb +69 -315
  53. data/spec/filters/bugs/struct.rb +0 -16
  54. data/spec/filters/unsupported/encoding.rb +7 -0
  55. data/spec/filters/unsupported/float.rb +3 -0
  56. data/spec/filters/unsupported/integer_size.rb +52 -0
  57. data/spec/filters/unsupported/marshal.rb +4 -0
  58. data/spec/filters/unsupported/mutable_strings.rb +37 -0
  59. data/spec/filters/unsupported/private_methods.rb +11 -0
  60. data/spec/filters/unsupported/rational_numbers.rb +4 -0
  61. data/spec/filters/unsupported/regular_expressions.rb +47 -0
  62. data/spec/filters/unsupported/symbols.rb +7 -0
  63. data/spec/filters/unsupported/tainted.rb +23 -1
  64. data/spec/filters/unsupported/trusted.rb +5 -0
  65. data/spec/lib/fixtures/complex_sprockets.js.rb.erb +4 -0
  66. data/spec/lib/fixtures/jst_file.js.jst +1 -0
  67. data/spec/lib/parser/call_spec.rb +19 -0
  68. data/spec/lib/parser/def_spec.rb +6 -0
  69. data/spec/lib/sprockets/erb_spec.rb +17 -4
  70. data/spec/lib/sprockets/processor_spec.rb +50 -18
  71. data/spec/lib/sprockets/server_spec.rb +39 -11
  72. data/spec/lib/tilt/opal_spec.rb +19 -0
  73. data/spec/opal/core/kernel/format_spec.rb +10 -10
  74. data/spec/opal/core/language/predefined_spec.rb +10 -0
  75. data/spec/opal/core/object_id_spec.rb +56 -0
  76. data/spec/opal/core/runtime/bridged_classes_spec.rb +4 -4
  77. data/spec/opal/core/runtime_spec.rb +7 -0
  78. data/spec/opal/stdlib/native/native_class_spec.rb +1 -1
  79. data/spec/opal/stdlib/promise/always_spec.rb +30 -0
  80. data/spec/opal/stdlib/promise/then_spec.rb +8 -0
  81. data/spec/opal/stdlib/promise/trace_spec.rb +8 -0
  82. data/spec/rubyspecs +15 -104
  83. data/spec/spec_helper.rb +4 -0
  84. data/stdlib/native.rb +7 -18
  85. data/stdlib/nodejs/file.rb +1 -1
  86. data/stdlib/opal-parser.rb +1 -0
  87. data/stdlib/pp.rb +7 -5
  88. data/stdlib/promise.rb +53 -41
  89. data/tasks/testing.rake +8 -6
  90. metadata +28 -14
  91. data/spec/filters/bugs/match_data.rb +0 -13
  92. data/spec/filters/bugs/numeric.rb +0 -22
  93. data/spec/filters/bugs/regexp.rb +0 -9
  94. data/spec/filters/bugs/unknown.rb +0 -11
@@ -1,12 +1,4 @@
1
1
  opal_filter "Struct" do
2
- fails "Struct includes Enumerable"
3
- fails "Struct anonymous class instance methods includes Enumerable"
4
-
5
- fails "Struct#[] fails when it does not know about the requested attribute"
6
- fails "Struct#[] fails if not passed a string, symbol, or integer"
7
-
8
- fails "Struct#[]= fails when trying to assign attributes which don't exist"
9
-
10
2
  fails "Struct#== returns true if the other has all the same fields"
11
3
  fails "Struct#== handles recursive structures by returning false if a difference can be found"
12
4
 
@@ -19,9 +11,6 @@ opal_filter "Struct" do
19
11
 
20
12
  fails "Struct#members does not override the instance accessor method"
21
13
 
22
- fails "Struct#to_h returns a Hash with members as keys"
23
- fails "Struct#to_h returns a Hash that is independent from the struct"
24
-
25
14
  fails "Struct#initialize can be overriden"
26
15
 
27
16
  fails "Struct#inspect returns a string representation of some kind"
@@ -37,9 +26,4 @@ opal_filter "Struct" do
37
26
  fails "Struct.new does not create a constant with symbol as first argument"
38
27
  fails "Struct.new creates a new anonymous class with nil first argument"
39
28
  fails "Struct.new calls to_str on its first argument (constant name)"
40
-
41
- fails "Struct#values_at fails when passed unsupported types"
42
- fails "Struct#values_at returns an array of values"
43
-
44
- fails "Struct anonymous class instance methods Enumerable methods should work"
45
29
  end
@@ -41,6 +41,8 @@ opal_filter "Encoding" do
41
41
  fails "String.allocate returns a fully-formed String"
42
42
  fails "String.allocate returns a binary String"
43
43
 
44
+ fails "String.new returns a binary String"
45
+
44
46
  fails "String#capitalize is locale insensitive (only upcases a-z and only downcases A-Z)"
45
47
 
46
48
  fails "String#chars is unicode aware"
@@ -58,6 +60,7 @@ opal_filter "Encoding" do
58
60
  fails "String#gsub with pattern and block uses the compatible encoding if they are compatible"
59
61
  fails "String#gsub with pattern and block raises an Encoding::CompatibilityError if the encodings are not compatible"
60
62
  fails "String#gsub with pattern and block replaces the incompatible part properly even if the encodings are not compatible"
63
+ fails "String#gsub with pattern and block raises an ArgumentError if encoding is not valid"
61
64
 
62
65
  fails "String#initialize with an argument carries over the encoding invalidity"
63
66
 
@@ -80,6 +83,10 @@ opal_filter "Encoding" do
80
83
  fails "Magic comment must be at the first line"
81
84
  fails "Magic comment is case-insensitive"
82
85
  fails "Magic comment determines __ENCODING__"
86
+
87
+ # Opal uses \u notation exclusively for String#inspect
88
+ fails "String#inspect returns a string with non-printing characters replaced by \\x notation"
89
+ fails "String#inspect returns a string with a NUL character replaced by \\000"
83
90
  end
84
91
 
85
92
  opal_filter "Regexp.escape" do
@@ -3,4 +3,7 @@ opal_filter "Float" do
3
3
  fails "Array#to_s represents a recursive element with '[...]'"
4
4
  fails "Array#eql? returns false if any corresponding elements are not #eql?"
5
5
  fails "Set#eql? returns true when the passed argument is a Set and contains the same elements"
6
+
7
+ fails "Kernel#Float raises a TypeError if #to_f returns an Integer"
8
+ fails "Kernel.Float raises a TypeError if #to_f returns an Integer"
6
9
  end
@@ -1,7 +1,59 @@
1
1
  opal_filter "fixnum and array size" do
2
2
  fails "Array#slice raises a RangeError when the length is out of range of Fixnum"
3
3
  fails "Array#slice raises a RangeError when the start index is out of range of Fixnum"
4
+
4
5
  fails "Array#fill with (filler, index, length) raises an ArgumentError or RangeError for too-large sizes"
6
+
5
7
  fails "Array#[] raises a RangeError when the length is out of range of Fixnum"
6
8
  fails "Array#[] raises a RangeError when the start index is out of range of Fixnum"
9
+
10
+ fails "Kernel.Integer returns a Fixnum or Bignum object"
11
+ fails "Kernel#Integer returns a Fixnum or Bignum object"
12
+
13
+ fails "String#% supports negative bignums with %u or %d"
14
+
15
+ fails "String#to_i with bases parses a String in base 2"
16
+ fails "String#to_i with bases parses a String in base 3"
17
+ fails "String#to_i with bases parses a String in base 4"
18
+ fails "String#to_i with bases parses a String in base 5"
19
+ fails "String#to_i with bases parses a String in base 6"
20
+ fails "String#to_i with bases parses a String in base 7"
21
+ fails "String#to_i with bases parses a String in base 8"
22
+ fails "String#to_i with bases parses a String in base 9"
23
+ fails "String#to_i with bases parses a String in base 10"
24
+ fails "String#to_i with bases parses a String in base 11"
25
+ fails "String#to_i with bases parses a String in base 12"
26
+ fails "String#to_i with bases parses a String in base 13"
27
+ fails "String#to_i with bases parses a String in base 14"
28
+ fails "String#to_i with bases parses a String in base 15"
29
+ fails "String#to_i with bases parses a String in base 16"
30
+ fails "String#to_i with bases parses a String in base 17"
31
+ fails "String#to_i with bases parses a String in base 18"
32
+ fails "String#to_i with bases parses a String in base 19"
33
+ fails "String#to_i with bases parses a String in base 20"
34
+ fails "String#to_i with bases parses a String in base 21"
35
+ fails "String#to_i with bases parses a String in base 22"
36
+ fails "String#to_i with bases parses a String in base 23"
37
+ fails "String#to_i with bases parses a String in base 24"
38
+ fails "String#to_i with bases parses a String in base 25"
39
+ fails "String#to_i with bases parses a String in base 26"
40
+ fails "String#to_i with bases parses a String in base 27"
41
+ fails "String#to_i with bases parses a String in base 28"
42
+ fails "String#to_i with bases parses a String in base 29"
43
+ fails "String#to_i with bases parses a String in base 30"
44
+ fails "String#to_i with bases parses a String in base 31"
45
+ fails "String#to_i with bases parses a String in base 32"
46
+ fails "String#to_i with bases parses a String in base 33"
47
+ fails "String#to_i with bases parses a String in base 34"
48
+ fails "String#to_i with bases parses a String in base 35"
49
+ fails "String#to_i with bases parses a String in base 36"
50
+
51
+ fails "Fixnum#<< with n << m returns a Bignum == fixnum_min() * 2 when fixnum_min() << 1 and n < 0"
52
+ fails "Fixnum#<< with n << m returns a Bignum == fixnum_max() * 2 when fixnum_max() << 1 and n > 0"
53
+ fails "Fixnum#<< with n << m returns 0 when m < 0 and m is a Bignum"
54
+ fails "Fixnum#<< with n << m returns 0 when m < 0 and m == p where 2**p > n >= 2**(p-1)"
55
+
56
+ fails "Fixnum#>> with n >> m returns a Bignum == fixnum_max() * 2 when fixnum_max() >> -1 and n > 0"
57
+ fails "Fixnum#>> with n >> m returns a Bignum == fixnum_min() * 2 when fixnum_min() >> -1 and n < 0"
58
+ fails "Fixnum#>> with n >> m returns 0 when m is a Bignum"
7
59
  end
@@ -0,0 +1,4 @@
1
+ opal_filter "Singleton" do
2
+ fails "Singleton#_dump returns an empty string"
3
+ fails "Singleton#_dump returns an empty string from a singleton subclass"
4
+ end
@@ -1,4 +1,21 @@
1
1
  opal_filter "Mutable strings are not supported in Opal" do
2
+ fails "String.new returns a new string given a string argument"
3
+ fails "String.new returns a fully-formed String"
4
+
5
+ fails "String#+ when self is in an ASCII-incompatible encoding incompatible with the argument's encoding uses self's encoding if both are empty"
6
+ fails "String#+ when self is in an ASCII-incompatible encoding incompatible with the argument's encoding uses self's encoding if the argument is empty"
7
+ fails "String#+ when self is in an ASCII-incompatible encoding incompatible with the argument's encoding uses the argument's encoding if self is empty"
8
+ fails "String#+ when self is in an ASCII-incompatible encoding incompatible with the argument's encoding raises Encoding::CompatibilityError if neither are empty"
9
+ fails "String#+ when the argument is in an ASCII-incompatible encoding incompatible with self's encoding uses self's encoding if both are empty"
10
+ fails "String#+ when the argument is in an ASCII-incompatible encoding incompatible with self's encoding uses self's encoding if the argument is empty"
11
+ fails "String#+ when the argument is in an ASCII-incompatible encoding incompatible with self's encoding uses the argument's encoding if self is empty"
12
+ fails "String#+ when the argument is in an ASCII-incompatible encoding incompatible with self's encoding raises Encoding::CompatibilityError if neither are empty"
13
+ fails "String#+ when self and the argument are in different ASCII-compatible encodings uses self's encoding if both are ASCII-only"
14
+ fails "String#+ when self and the argument are in different ASCII-compatible encodings uses self's encoding if the argument is ASCII-only"
15
+ fails "String#+ when self and the argument are in different ASCII-compatible encodings uses the argument's encoding if self is ASCII-only"
16
+ fails "String#+ when self and the argument are in different ASCII-compatible encodings raises Encoding::CompatibilityError if neither are ASCII-only"
17
+ fails "String#+ when self is ASCII-8BIT and argument is US-ASCII uses ASCII-8BIT encoding"
18
+
2
19
  fails "String#upcase! raises a RuntimeError when self is frozen"
3
20
  fails "String#upcase! returns nil if no modifications were made"
4
21
  fails "String#upcase! modifies self in place"
@@ -98,6 +115,8 @@ opal_filter "Mutable strings are not supported in Opal" do
98
115
  fails "String#chop! raises a RuntimeError on a frozen instance that is modified"
99
116
  fails "String#chop! raises a RuntimeError on a frozen instance that would not be modified"
100
117
 
118
+ fails "String#sub with pattern and block doesn't raise a RuntimeError if the string is modified while substituting"
119
+
101
120
  fails "String#gsub! with pattern and Hash returns self with all occurrences of pattern replaced with the value of the corresponding hash key"
102
121
  fails "String#gsub! with pattern and Hash ignores keys that don't correspond to matches"
103
122
  fails "String#gsub! with pattern and Hash replaces self with an empty string if the pattern matches but the hash specifies no replacements"
@@ -126,6 +145,7 @@ opal_filter "Mutable strings are not supported in Opal" do
126
145
  fails "String#gsub! with pattern and block uses the compatible encoding if they are compatible"
127
146
  fails "String#gsub! with pattern and block raises an Encoding::CompatibilityError if the encodings are not compatible"
128
147
  fails "String#gsub! with pattern and block replaces the incompatible part properly even if the encodings are not compatible"
148
+ fails "String#gsub! with pattern and block raises an ArgumentError if encoding is not valid"
129
149
 
130
150
  fails "String#lstrip! modifies self in place and returns self"
131
151
  fails "String#lstrip! returns nil if no modifications were made"
@@ -358,4 +378,21 @@ opal_filter "Mutable strings are not supported in Opal" do
358
378
  fails "String#concat when self and the argument are in different ASCII-compatible encodings uses the argument's encoding if self is ASCII-only"
359
379
  fails "String#concat when self and the argument are in different ASCII-compatible encodings raises Encoding::CompatibilityError if neither are ASCII-only"
360
380
  fails "String#concat when self is ASCII-8BIT and argument is US-ASCII uses ASCII-8BIT encoding"
381
+
382
+ fails "String#dup does not modify the original string when changing dupped string"
383
+
384
+ fails "String#each_line does not care if the string is modified while substituting"
385
+ fails "String#lines does not care if the string is modified while substituting"
386
+
387
+ fails "String#initialize with an argument raises a RuntimeError on a frozen instance when self-replacing"
388
+ fails "String#initialize with an argument raises a RuntimeError on a frozen instance that is modified"
389
+ fails "String#initialize with an argument raises a TypeError if other can't be converted to string"
390
+ fails "String#initialize with an argument tries to convert other to string using to_str"
391
+ fails "String#initialize with an argument replaces the encoding of self with that of other"
392
+ fails "String#initialize with an argument does not trust self if other is trusted"
393
+ fails "String#initialize with an argument untrusts self if other is untrusted"
394
+ fails "String#initialize with an argument does not untaint self if other is untainted"
395
+ fails "String#initialize with an argument taints self if other is tainted"
396
+ fails "String#initialize with an argument replaces the content of self with other"
397
+ fails "String#initialize with an argument returns self"
361
398
  end
@@ -40,5 +40,16 @@ opal_filter "Private methods" do
40
40
 
41
41
  fails "Math#atanh is a private instance method"
42
42
 
43
+ fails "Kernel has private instance method Array()"
44
+ fails "Kernel has private instance method Hash()"
45
+ fails "Kernel#Integer is a private method"
46
+ fails "Kernel#Float is a private method"
47
+ fails "Kernel#format is a private method"
48
+ fails "Kernel#sprintf is a private method"
49
+ fails "Kernel#String is a private method"
43
50
  fails "Kernel#warn is a private method"
51
+
52
+ fails "Module#instance_methods makes a private Object instance method public in Kernel"
53
+
54
+ fails "String#initialize is a private method"
44
55
  end
@@ -0,0 +1,4 @@
1
+ opal_filter "rational_numbers" do
2
+ fails "Kernel.Integer calls to_i on Rationals"
3
+ fails "Kernel#Integer calls to_i on Rationals"
4
+ end
@@ -0,0 +1,47 @@
1
+ opal_filter "regular_expressions" do
2
+ fails "MatchData#[Symbol] returns the corresponding named match when given a Symbol"
3
+ fails "MatchData#[Symbol] returns the corresponding named match when given a String"
4
+ fails "MatchData#[Symbol] returns the matching version of multiple corresponding named match"
5
+ fails "MatchData#[Symbol] returns the last match when multiple named matches exist with the same name"
6
+ fails "MatchData#[Symbol] returns nil on non-matching named matches"
7
+ fails "MatchData#[Symbol] raises an IndexError if there is no named match corresponding to the Symbol"
8
+ fails "MatchData#[Symbol] raises an IndexError if there is no named match corresponding to the String"
9
+ fails "MatchData#[Symbol] returns matches in the String's encoding"
10
+
11
+ fails "MatchData#begin returns the offset of the start of the nth element"
12
+ fails "MatchData#begin returns nil when the nth match isn't found"
13
+ fails "MatchData#begin returns the offset for multi byte strings"
14
+ fails "MatchData#begin returns the offset for multi byte strings with unicode regexp"
15
+
16
+ fails "MatchData#end returns the offset of the end of the nth element"
17
+ fails "MatchData#end returns nil when the nth match isn't found"
18
+ fails "MatchData#end returns the offset for multi byte strings"
19
+ fails "MatchData#end returns the offset for multi byte strings with unicode regexp"
20
+
21
+ fails "MatchData#names returns an Array"
22
+ fails "MatchData#names sets each element to a String"
23
+ fails "MatchData#names returns the names of the named capture groups"
24
+ fails "MatchData#names returns [] if there were no named captures"
25
+ fails "MatchData#names returns each name only once"
26
+ fails "MatchData#names equals Regexp#names"
27
+
28
+ fails "MatchData#offset returns a two element array with the begin and end of the nth match"
29
+ fails "MatchData#offset returns [nil, nil] when the nth match isn't found"
30
+ fails "MatchData#offset returns the offset for multi byte strings"
31
+ fails "MatchData#offset returns the offset for multi byte strings with unicode regexp"
32
+
33
+ fails "MatchData#regexp returns the pattern used in the match"
34
+
35
+ fails "String#gsub with pattern and replacement replaces \\k named backreferences with the regexp's corresponding capture"
36
+ fails "String#gsub with pattern and replacement doesn't freak out when replacing ^" #Only fails "Text\nFoo".gsub(/^/, ' ').should == " Text\n Foo"
37
+ fails "String#gsub with pattern and replacement supports \\G which matches at the beginning of the remaining (non-matched) string"
38
+ fails "String#gsub with pattern and replacement returns a copy of self with all occurrences of pattern replaced with replacement" #Only fails str.gsub(/\Ah\S+\s*/, "huh? ").should == "huh? homely world. hah!"
39
+
40
+ fails "String#index with Regexp supports \\G which matches at the given start offset"
41
+
42
+ fails "String#match matches \\G at the start of the string"
43
+
44
+ fails "String#scan supports \\G which matches the end of the previous match / string start for first match"
45
+
46
+ fails "String#sub with pattern, replacement supports \\G which matches at the beginning of the string"
47
+ end
@@ -7,4 +7,11 @@ opal_filter "Symbols" do
7
7
  fails "A Symbol literal can be created by the %s-delimited expression"
8
8
  fails "A Symbol literal can contain null in the string"
9
9
  fails "A Symbol literal can be an empty string"
10
+
11
+ fails "String#each_line raises a TypeError when the separator is a symbol"
12
+ fails "String#gsub with pattern and Hash ignores non-String keys"
13
+ fails "String#index raises a TypeError if passed a Symbol"
14
+ fails "String#lines raises a TypeError when the separator is a symbol"
15
+ fails "String#sub with pattern and Hash ignores non-String keys"
16
+ fails "String#upto does not work with symbols"
10
17
  end
@@ -67,6 +67,14 @@ opal_filter 'tainted' do
67
67
  fails "Hash#to_s returns a tainted string if self is tainted and not empty"
68
68
  fails "Hash#inspect returns a tainted string if self is tainted and not empty"
69
69
 
70
+ fails "String#% always taints the result when the format string is tainted"
71
+ fails "String#% taints result for %p when argument.inspect is tainted"
72
+ fails "String#% taints result for %s when argument is tainted"
73
+
74
+ fails "String#+ taints the result when self or other is tainted"
75
+
76
+ fails "String#* always taints the result when self is tainted"
77
+
70
78
  fails "String#[] with index, length always taints resulting strings when self is tainted"
71
79
  fails "String#[] with Range always taints resulting strings when self is tainted"
72
80
  fails "String#[] with Regexp always taints resulting strings when self or regexp is tainted"
@@ -90,12 +98,16 @@ opal_filter 'tainted' do
90
98
 
91
99
  fails "String#chop taints result when self is tainted"
92
100
 
101
+ fails "String#delete taints result when self is tainted"
102
+
93
103
  fails "String#each_line taints substrings that are passed to the block if self is tainted"
94
104
 
95
105
  fails "String#gsub with pattern and replacement taints the result if the original string or replacement is tainted"
96
106
  fails "String#gsub with pattern and Hash taints the result if the original string is tainted"
97
107
  fails "String#gsub with pattern and Hash taints the result if a hash value is tainted"
98
108
 
109
+ fails "String#inspect taints the result if self is tainted"
110
+
99
111
  fails "String#lines taints substrings that are passed to the block if self is tainted"
100
112
 
101
113
  fails "String#ljust with length, padding taints result when self or padstr is tainted"
@@ -110,9 +122,17 @@ opal_filter 'tainted' do
110
122
  fails "String#rjust with length, padding taints result when self or padstr is tainted"
111
123
  fails "String#rjust with length, padding when padding is tainted and self is untainted returns a tainted string if and only if length is longer than self"
112
124
 
113
-
114
125
  fails "String#rstrip taints the result when self is tainted"
115
126
 
127
+ fails "String#scan taints the results if the String argument is tainted"
128
+ fails "String#scan taints the results when passed a String argument if self is tainted"
129
+ fails "String#scan taints the results if the Regexp argument is tainted"
130
+ fails "String#scan taints the results when passed a Regexp argument if self is tainted"
131
+ fails "String#scan with pattern and block taints the results if the String argument is tainted"
132
+ fails "String#scan with pattern and block taints the results when passed a String argument if self is tainted"
133
+ fails "String#scan with pattern and block taints the results if the Regexp argument is tainted"
134
+ fails "String#scan with pattern and block taints the results when passed a Regexp argument if self is tainted"
135
+
116
136
  fails "String#slice with index, length always taints resulting strings when self is tainted"
117
137
  fails "String#slice with Range always taints resulting strings when self is tainted"
118
138
  fails "String#slice with Regexp always taints resulting strings when self or regexp is tainted"
@@ -132,6 +152,8 @@ opal_filter 'tainted' do
132
152
 
133
153
  fails "String#sub with pattern, replacement taints the result if the original string or replacement is tainted"
134
154
  fails "String#sub with pattern and block taints the result if the original string or replacement is tainted"
155
+ fails "String#sub with pattern and Hash taints the result if a hash value is tainted"
156
+ fails "String#sub with pattern and Hash taints the result if the original string is tainted"
135
157
 
136
158
  fails "String#succ taints the result if self is tainted"
137
159
 
@@ -78,6 +78,11 @@ opal_filter "Object#trusted/untrusted" do
78
78
  fails "String#gsub with pattern and Hash untrusts the result if a hash value is untrusted"
79
79
  fails "String#gsub with pattern and block untrusts the result if the original string or replacement is untrusted"
80
80
 
81
+ fails "String#inspect untrusts the result if self is untrusted"
82
+
83
+ fails "String#sub with pattern and Hash untrusts the result if the original string is untrusted"
84
+ fails "String#sub with pattern and Hash untrusts the result if a hash value is untrusted"
85
+
81
86
  fails "MatchData#pre_match keeps untrusted status from the source string"
82
87
  fails "MatchData#post_match keeps untrusted status from the source string"
83
88
  end
@@ -0,0 +1,4 @@
1
+ #= require no_requires
2
+ //= require jst_file
3
+ #= require_tree ./required_tree_test
4
+ require 'file_with_directives'
@@ -0,0 +1 @@
1
+ #= require sprockets_file
@@ -144,3 +144,22 @@ describe "Command calls without a space" do
144
144
  [:arglist, [:sym, :+]]]
145
145
  end
146
146
  end
147
+
148
+ describe 'Operator calls followed by parens' do
149
+ it 'correctly parses parens' do
150
+ parsed('1/(2)').should == [:call, [:int, 1], '/'.to_sym, [:arglist, [:paren, [:int, 2]]]]
151
+ parsed('1*(2)').should == [:call, [:int, 1], '*'.to_sym, [:arglist, [:paren, [:int, 2]]]]
152
+ parsed('1+(2)').should == [:call, [:int, 1], '+'.to_sym, [:arglist, [:paren, [:int, 2]]]]
153
+ parsed('1-(2)').should == [:call, [:int, 1], '-'.to_sym, [:arglist, [:paren, [:int, 2]]]]
154
+ end
155
+ end
156
+
157
+ describe 'Calls with trailing comma' do
158
+ it 'parses correctly' do
159
+ parsed('foo(1,)').should == [:call, nil, :foo, [:arglist, [:int, 1]]]
160
+ parsed('foo(1, 2,)').should == [:call, nil, :foo, [:arglist, [:int, 1], [:int, 2]]]
161
+
162
+ parsed('foo(a: 100,)').should == [:call, nil, :foo, [:arglist,
163
+ [:hash, [:sym, :a], [:int, 100]]]]
164
+ end
165
+ end
@@ -70,5 +70,11 @@ describe "The def keyword" do
70
70
  it "should parse combinations of keyword args" do
71
71
  parsed("def foo(a:, b: 1, **c); end")[3].should == [:args, [:kwarg, :a], [:kwoptarg, :b, [:int, 1]], [:kwrestarg, :c]]
72
72
  end
73
+
74
+ it "should parse keywords without parens" do
75
+ parsed("def foo a:; end")[3].should == [:args, [:kwarg, :a]]
76
+ parsed("def foo a:, b:; end")[3].should == [:args, [:kwarg, :a], [:kwarg, :b]]
77
+ parsed("def foo a: 1, b: 2; end")[3].should == [:args, [:kwoptarg, :a, [:int, 1]], [:kwoptarg, :b, [:int, 2]]]
78
+ end
73
79
  end
74
80
  end
@@ -3,10 +3,23 @@ require 'opal/sprockets/erb'
3
3
 
4
4
  describe Opal::ERB::Processor do
5
5
  let(:pathname) { Pathname("/Code/app/mylib/opal/foo.#{ext}") }
6
- let(:_context) { double('_context', :logical_path => "foo.#{ext}", :pathname => pathname) }
6
+ let(:environment) { double(Sprockets::Environment,
7
+ cache: nil,
8
+ :[] => nil,
9
+ resolve: pathname.expand_path.to_s,
10
+ engines: double(keys: %w[.rb .js .erb .opal]),
11
+ ) }
12
+ let(:sprockets_context) { double(Sprockets::Context,
13
+ logical_path: "foo.#{ext}",
14
+ environment: environment,
15
+ pathname: pathname,
16
+ filename: pathname.to_s,
17
+ root_path: '/Code/app/mylib',
18
+ is_a?: true,
19
+ ) }
7
20
  let(:required_assets) { [] }
8
21
  let(:template) { described_class.new { |t| %Q{<a href="<%= url %>"><%= name %></a>} } }
9
- before { _context.stub(:require_asset) {|asset| required_assets << asset } }
22
+ before { sprockets_context.stub(:require_asset) {|asset| required_assets << asset } }
10
23
 
11
24
  let(:ext) { 'opalerb' }
12
25
 
@@ -15,11 +28,11 @@ describe Opal::ERB::Processor do
15
28
  end
16
29
 
17
30
  it 'renders the template' do
18
- expect(template.render(_context)).to include('"<a href=\""')
31
+ expect(template.render(sprockets_context)).to include('"<a href=\""')
19
32
  end
20
33
 
21
34
  it 'implicitly requires "erb"' do
22
- template.render(_context)
35
+ template.render(sprockets_context)
23
36
  expect(required_assets).to eq(['erb'])
24
37
  end
25
38
  end
@@ -3,33 +3,65 @@ require 'opal/sprockets/processor'
3
3
 
4
4
  describe Opal::Processor do
5
5
  let(:pathname) { Pathname("/Code/app/mylib/opal/foo.#{ext}") }
6
- let(:_context) { double('_context', :logical_path => "foo.#{ext}", :pathname => pathname) }
7
- let(:env) { double('env') }
6
+ let(:environment) { double(Sprockets::Environment,
7
+ cache: nil,
8
+ :[] => nil,
9
+ resolve: pathname.expand_path.to_s,
10
+ engines: double(keys: %w[.rb .js .opal]),
11
+ ) }
12
+ let(:sprockets_context) { double(Sprockets::Context,
13
+ logical_path: "foo.#{ext}",
14
+ environment: environment,
15
+ pathname: pathname,
16
+ filename: pathname.to_s,
17
+ root_path: '/Code/app/mylib',
18
+ is_a?: true,
19
+ ) }
8
20
 
9
- before do
10
- env.stub(:resolve) { pathname.expand_path.to_s }
11
- env.stub(:[])
12
- _context.stub(:environment) { env }
13
- end
14
-
15
- %w[rb js.rb opal js.opal].each do |ext|
21
+ %w[.rb .opal].each do |ext|
16
22
  let(:ext) { ext }
17
23
 
18
- describe %Q{with extension ".#{ext}"} do
19
- it "is registered for '.#{ext}' files" do
20
- expect(Tilt["test.#{ext}"]).to eq(described_class)
24
+ describe %Q{with extension "#{ext}"} do
25
+ it "is registered for '#{ext}' files" do
26
+ expect(Sprockets.engines[ext]).to eq(described_class)
21
27
  end
22
28
 
23
29
  it "compiles and evaluates the template on #render" do
24
30
  template = described_class.new { |t| "puts 'Hello, World!'\n" }
25
- expect(template.render(_context)).to include('"Hello, World!"')
26
- end
27
-
28
- it "can be rendered more than once" do
29
- template = described_class.new(_context) { |t| "puts 'Hello, World!'\n" }
30
- 3.times { expect(template.render(_context)).to include('"Hello, World!"') }
31
+ expect(template.render(sprockets_context)).to include('"Hello, World!"')
31
32
  end
32
33
  end
33
34
  end
34
35
 
36
+ describe '.stubbed_files' do
37
+ around do |e|
38
+ described_class.stubbed_files.clear
39
+ e.run
40
+ described_class.stubbed_files.clear
41
+ end
42
+
43
+ let(:stubbed_file) { 'foo' }
44
+ let(:template) { described_class.new { |t| "require #{stubbed_file.inspect}" } }
45
+
46
+ it 'usually require files' do
47
+ sprockets_context.should_receive(:require_asset).with(stubbed_file)
48
+ template.render(sprockets_context)
49
+ end
50
+
51
+ it 'skips require of stubbed file' do
52
+ described_class.stub_file stubbed_file
53
+ sprockets_context.should_not_receive(:require_asset).with(stubbed_file)
54
+ template.render(sprockets_context)
55
+ end
56
+
57
+ it 'marks a stubbed file as loaded' do
58
+ described_class.stub_file stubbed_file
59
+ asset = double(dependencies: [], pathname: Pathname('bar'), logical_path: 'bar')
60
+ environment.stub(:[]).with('bar.js') { asset }
61
+ environment.stub(:engines) { {'.rb' => described_class, '.opal' => described_class} }
62
+
63
+ code = described_class.load_asset_code(environment, 'bar')
64
+ code.should match stubbed_file
65
+ end
66
+ end
35
67
  end