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.
- checksums.yaml +4 -4
- data/.travis.yml +6 -1
- data/CHANGELOG.md +29 -0
- data/CONTRIBUTING.md +51 -4
- data/Gemfile +3 -0
- data/README.md +5 -5
- data/config.ru +1 -1
- data/examples/sinatra/Gemfile +1 -0
- data/examples/sinatra/config.ru +13 -3
- data/lib/mspec/opal/rake_task.rb +21 -30
- data/lib/mspec/opal/runner.rb +37 -0
- data/lib/mspec/opal/special_calls.rb +6 -0
- data/lib/opal/builder.rb +1 -0
- data/lib/opal/builder_processors.rb +5 -2
- data/lib/opal/cli_runners/phantom.js +10 -1
- data/lib/opal/compiler.rb +6 -3
- data/lib/opal/config.rb +48 -0
- data/lib/opal/nodes/call.rb +3 -2
- data/lib/opal/nodes/literal.rb +19 -2
- data/lib/opal/parser/grammar.rb +2224 -2196
- data/lib/opal/parser/grammar.y +25 -7
- data/lib/opal/parser/lexer.rb +12 -9
- data/lib/opal/path_reader.rb +1 -1
- data/lib/opal/sprockets/erb.rb +6 -20
- data/lib/opal/sprockets/path_reader.rb +4 -2
- data/lib/opal/sprockets/processor.rb +135 -80
- data/lib/opal/sprockets/server.rb +49 -78
- data/lib/opal/sprockets/source_map_header_patch.rb +41 -0
- data/lib/opal/sprockets/source_map_server.rb +115 -0
- data/lib/opal/version.rb +1 -1
- data/lib/tilt/opal.rb +48 -0
- data/opal.gemspec +1 -1
- data/opal/corelib/array.rb +179 -51
- data/opal/corelib/array/inheritance.rb +14 -0
- data/opal/corelib/boolean.rb +5 -0
- data/opal/corelib/hash.rb +1 -1
- data/opal/corelib/kernel.rb +660 -164
- data/opal/corelib/match_data.rb +44 -21
- data/opal/corelib/module.rb +83 -53
- data/opal/corelib/numeric.rb +15 -1
- data/opal/corelib/regexp.rb +31 -75
- data/opal/corelib/runtime.js +20 -8
- data/opal/corelib/string.rb +754 -243
- data/opal/corelib/string/inheritance.rb +20 -3
- data/opal/corelib/struct.rb +30 -6
- data/opal/corelib/variables.rb +2 -2
- data/spec/filters/bugs/array.rb +0 -39
- data/spec/filters/bugs/kernel.rb +10 -7
- data/spec/filters/bugs/module.rb +21 -0
- data/spec/filters/bugs/opal.rb +0 -5
- data/spec/filters/bugs/singleton.rb +0 -2
- data/spec/filters/bugs/string.rb +69 -315
- data/spec/filters/bugs/struct.rb +0 -16
- data/spec/filters/unsupported/encoding.rb +7 -0
- data/spec/filters/unsupported/float.rb +3 -0
- data/spec/filters/unsupported/integer_size.rb +52 -0
- data/spec/filters/unsupported/marshal.rb +4 -0
- data/spec/filters/unsupported/mutable_strings.rb +37 -0
- data/spec/filters/unsupported/private_methods.rb +11 -0
- data/spec/filters/unsupported/rational_numbers.rb +4 -0
- data/spec/filters/unsupported/regular_expressions.rb +47 -0
- data/spec/filters/unsupported/symbols.rb +7 -0
- data/spec/filters/unsupported/tainted.rb +23 -1
- data/spec/filters/unsupported/trusted.rb +5 -0
- data/spec/lib/fixtures/complex_sprockets.js.rb.erb +4 -0
- data/spec/lib/fixtures/jst_file.js.jst +1 -0
- data/spec/lib/parser/call_spec.rb +19 -0
- data/spec/lib/parser/def_spec.rb +6 -0
- data/spec/lib/sprockets/erb_spec.rb +17 -4
- data/spec/lib/sprockets/processor_spec.rb +50 -18
- data/spec/lib/sprockets/server_spec.rb +39 -11
- data/spec/lib/tilt/opal_spec.rb +19 -0
- data/spec/opal/core/kernel/format_spec.rb +10 -10
- data/spec/opal/core/language/predefined_spec.rb +10 -0
- data/spec/opal/core/object_id_spec.rb +56 -0
- data/spec/opal/core/runtime/bridged_classes_spec.rb +4 -4
- data/spec/opal/core/runtime_spec.rb +7 -0
- data/spec/opal/stdlib/native/native_class_spec.rb +1 -1
- data/spec/opal/stdlib/promise/always_spec.rb +30 -0
- data/spec/opal/stdlib/promise/then_spec.rb +8 -0
- data/spec/opal/stdlib/promise/trace_spec.rb +8 -0
- data/spec/rubyspecs +15 -104
- data/spec/spec_helper.rb +4 -0
- data/stdlib/native.rb +7 -18
- data/stdlib/nodejs/file.rb +1 -1
- data/stdlib/opal-parser.rb +1 -0
- data/stdlib/pp.rb +7 -5
- data/stdlib/promise.rb +53 -41
- data/tasks/testing.rake +8 -6
- metadata +28 -14
- data/spec/filters/bugs/match_data.rb +0 -13
- data/spec/filters/bugs/numeric.rb +0 -22
- data/spec/filters/bugs/regexp.rb +0 -9
- data/spec/filters/bugs/unknown.rb +0 -11
data/opal/corelib/match_data.rb
CHANGED
@@ -6,8 +6,8 @@ class MatchData
|
|
6
6
|
@regexp = regexp
|
7
7
|
@begin = `match_groups.index`
|
8
8
|
@string = `match_groups.input`
|
9
|
-
@pre_match =
|
10
|
-
@post_match =
|
9
|
+
@pre_match = `match_groups.input.slice(0, match_groups.index)`
|
10
|
+
@post_match = `match_groups.input.slice(match_groups.index + match_groups[0].length)`
|
11
11
|
@matches = []
|
12
12
|
|
13
13
|
%x{
|
@@ -28,22 +28,43 @@ class MatchData
|
|
28
28
|
@matches[*args]
|
29
29
|
end
|
30
30
|
|
31
|
+
def offset(n)
|
32
|
+
%x{
|
33
|
+
if (n !== 0) {
|
34
|
+
#{raise ArgumentError, 'MatchData#offset only supports 0th element'}
|
35
|
+
}
|
36
|
+
return [self.begin, self.begin + self.matches[n].length];
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
31
40
|
def ==(other)
|
32
41
|
return false unless MatchData === other
|
33
42
|
|
34
43
|
`self.string == other.string` &&
|
35
|
-
`self.regexp == other.regexp` &&
|
44
|
+
`self.regexp.toString() == other.regexp.toString()` &&
|
36
45
|
`self.pre_match == other.pre_match` &&
|
37
46
|
`self.post_match == other.post_match` &&
|
38
47
|
`self.begin == other.begin`
|
39
48
|
end
|
40
49
|
|
41
|
-
|
42
|
-
if pos != 0 && pos != 1
|
43
|
-
raise ArgumentError, 'MatchData#begin only supports 0th element'
|
44
|
-
end
|
50
|
+
alias eql? ==
|
45
51
|
|
46
|
-
|
52
|
+
def begin(n)
|
53
|
+
%x{
|
54
|
+
if (n !== 0) {
|
55
|
+
#{raise ArgumentError, 'MatchData#begin only supports 0th element'}
|
56
|
+
}
|
57
|
+
return self.begin;
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def end(n)
|
62
|
+
%x{
|
63
|
+
if (n !== 0) {
|
64
|
+
#{raise ArgumentError, 'MatchData#end only supports 0th element'}
|
65
|
+
}
|
66
|
+
return self.begin + self.matches[n].length;
|
67
|
+
}
|
47
68
|
end
|
48
69
|
|
49
70
|
def captures
|
@@ -76,27 +97,29 @@ class MatchData
|
|
76
97
|
`#@matches[0]`
|
77
98
|
end
|
78
99
|
|
79
|
-
def values_at(*
|
100
|
+
def values_at(*args)
|
80
101
|
%x{
|
81
|
-
var values
|
82
|
-
match_length = #@matches.length;
|
102
|
+
var i, a, index, values = [];
|
83
103
|
|
84
|
-
for (
|
85
|
-
var pos = indexes[i];
|
104
|
+
for (i = 0; i < args.length; i++) {
|
86
105
|
|
87
|
-
if (
|
88
|
-
|
106
|
+
if (args[i].$$is_range) {
|
107
|
+
a = #{`args[i]`.to_a};
|
108
|
+
a.unshift(i, 1);
|
109
|
+
Array.prototype.splice.apply(args, a);
|
89
110
|
}
|
90
|
-
else {
|
91
|
-
pos += match_length;
|
92
111
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
112
|
+
index = #{Opal.coerce_to!(`args[i]`, Integer, :to_int)};
|
113
|
+
|
114
|
+
if (index < 0) {
|
115
|
+
index += #@matches.length;
|
116
|
+
if (index < 0) {
|
97
117
|
values.push(nil);
|
118
|
+
continue;
|
98
119
|
}
|
99
120
|
}
|
121
|
+
|
122
|
+
values.push(#@matches[index]);
|
100
123
|
}
|
101
124
|
|
102
125
|
return values;
|
data/opal/corelib/module.rb
CHANGED
@@ -92,20 +92,33 @@ class Module
|
|
92
92
|
attr_writer(*names)
|
93
93
|
end
|
94
94
|
|
95
|
+
alias attr attr_accessor
|
96
|
+
|
95
97
|
def attr_reader(*names)
|
96
98
|
%x{
|
97
|
-
|
98
|
-
(function(name) {
|
99
|
-
self.$$proto[name] = nil;
|
100
|
-
var func = function() { return this[name] };
|
99
|
+
var proto = self.$$proto;
|
101
100
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
101
|
+
for (var i = names.length - 1; i >= 0; i--) {
|
102
|
+
var name = names[i],
|
103
|
+
id = '$' + name;
|
104
|
+
|
105
|
+
// the closure here is needed because name will change at the next
|
106
|
+
// cycle, I wish we could use let.
|
107
|
+
var body = (function(name) {
|
108
|
+
return function() {
|
109
|
+
return this[name];
|
110
|
+
};
|
111
|
+
})(name);
|
112
|
+
|
113
|
+
// initialize the instance variable as nil
|
114
|
+
proto[name] = nil;
|
115
|
+
|
116
|
+
if (self.$$is_singleton) {
|
117
|
+
proto.constructor.prototype[id] = body;
|
118
|
+
}
|
119
|
+
else {
|
120
|
+
Opal.defn(self, id, body);
|
121
|
+
}
|
109
122
|
}
|
110
123
|
}
|
111
124
|
|
@@ -114,25 +127,35 @@ class Module
|
|
114
127
|
|
115
128
|
def attr_writer(*names)
|
116
129
|
%x{
|
117
|
-
|
118
|
-
(function(name) {
|
119
|
-
self.$$proto[name] = nil;
|
120
|
-
var func = function(value) { return this[name] = value; };
|
130
|
+
var proto = self.$$proto;
|
121
131
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
132
|
+
for (var i = names.length - 1; i >= 0; i--) {
|
133
|
+
var name = names[i],
|
134
|
+
id = '$' + name + '=';
|
135
|
+
|
136
|
+
// the closure here is needed because name will change at the next
|
137
|
+
// cycle, I wish we could use let.
|
138
|
+
var body = (function(name){
|
139
|
+
return function(value) {
|
140
|
+
return this[name] = value;
|
127
141
|
}
|
128
|
-
})(
|
142
|
+
})(name);
|
143
|
+
|
144
|
+
// initialize the instance variable as nil
|
145
|
+
proto[name] = nil;
|
146
|
+
|
147
|
+
if (self.$$is_singleton) {
|
148
|
+
proto.constructor.prototype[id] = body;
|
149
|
+
}
|
150
|
+
else {
|
151
|
+
Opal.defn(self, id, body);
|
152
|
+
}
|
129
153
|
}
|
130
154
|
}
|
155
|
+
|
131
156
|
nil
|
132
157
|
end
|
133
158
|
|
134
|
-
alias attr attr_accessor
|
135
|
-
|
136
159
|
def autoload(const, path)
|
137
160
|
%x{
|
138
161
|
var autoloaders;
|
@@ -176,15 +199,18 @@ class Module
|
|
176
199
|
|
177
200
|
%x{
|
178
201
|
scopes = [self.$$scope];
|
202
|
+
|
179
203
|
if (inherit || self === Opal.Object) {
|
180
204
|
var parent = self.$$super;
|
205
|
+
|
181
206
|
while (parent !== Opal.BasicObject) {
|
182
207
|
scopes.push(parent.$$scope);
|
208
|
+
|
183
209
|
parent = parent.$$super;
|
184
210
|
}
|
185
211
|
}
|
186
212
|
|
187
|
-
for (var i = 0,
|
213
|
+
for (var i = 0, length = scopes.length; i < length; i++) {
|
188
214
|
if (scopes[i].hasOwnProperty(name)) {
|
189
215
|
return true;
|
190
216
|
}
|
@@ -195,19 +221,24 @@ class Module
|
|
195
221
|
end
|
196
222
|
|
197
223
|
def const_get(name, inherit = true)
|
224
|
+
if name['::'] && name != '::'
|
225
|
+
return name.split('::').inject(self){|o, c| o.const_get(c)}
|
226
|
+
end
|
198
227
|
raise NameError, "wrong constant name #{name}" unless name =~ /^[A-Z]\w*$/
|
199
|
-
|
200
228
|
%x{
|
201
229
|
var scopes = [self.$$scope];
|
230
|
+
|
202
231
|
if (inherit || self == Opal.Object) {
|
203
232
|
var parent = self.$$super;
|
233
|
+
|
204
234
|
while (parent !== Opal.BasicObject) {
|
205
235
|
scopes.push(parent.$$scope);
|
236
|
+
|
206
237
|
parent = parent.$$super;
|
207
238
|
}
|
208
239
|
}
|
209
240
|
|
210
|
-
for (var i = 0,
|
241
|
+
for (var i = 0, length = scopes.length; i < length; i++) {
|
211
242
|
if (scopes[i].hasOwnProperty(name)) {
|
212
243
|
return scopes[i][name];
|
213
244
|
}
|
@@ -217,20 +248,20 @@ class Module
|
|
217
248
|
}
|
218
249
|
end
|
219
250
|
|
220
|
-
def const_missing(
|
251
|
+
def const_missing(name)
|
221
252
|
%x{
|
222
253
|
if (self.$$autoload) {
|
223
|
-
var file = self.$$autoload[
|
254
|
+
var file = self.$$autoload[name];
|
224
255
|
|
225
256
|
if (file) {
|
226
257
|
self.$require(file);
|
227
258
|
|
228
|
-
return #{const_get
|
259
|
+
return #{const_get name};
|
229
260
|
}
|
230
261
|
}
|
231
262
|
}
|
232
263
|
|
233
|
-
raise NameError, "uninitialized constant #{self}::#{
|
264
|
+
raise NameError, "uninitialized constant #{self}::#{name}"
|
234
265
|
end
|
235
266
|
|
236
267
|
def const_set(name, value)
|
@@ -247,26 +278,31 @@ class Module
|
|
247
278
|
value
|
248
279
|
end
|
249
280
|
|
250
|
-
def define_method(name, method =
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
}
|
281
|
+
def define_method(name, method = nil, &block)
|
282
|
+
unless method || block
|
283
|
+
raise ArgumentError, 'tried to create Proc object without a block'
|
284
|
+
end
|
255
285
|
|
256
|
-
|
257
|
-
|
258
|
-
|
286
|
+
if method
|
287
|
+
if Proc === method
|
288
|
+
block = method
|
289
|
+
else
|
290
|
+
raise TypeError, "wrong argument type #{method.class} (expected Proc/Method)"
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
%x{
|
295
|
+
var id = '$' + name;
|
259
296
|
|
260
|
-
var jsid = '$' + name;
|
261
297
|
block.$$jsid = name;
|
262
298
|
block.$$s = null;
|
263
299
|
block.$$def = block;
|
264
300
|
|
265
301
|
if (self.$$is_singleton) {
|
266
|
-
self.$$proto[
|
302
|
+
self.$$proto[id] = block;
|
267
303
|
}
|
268
304
|
else {
|
269
|
-
Opal.defn(self,
|
305
|
+
Opal.defn(self, id, block);
|
270
306
|
}
|
271
307
|
|
272
308
|
return name;
|
@@ -274,15 +310,9 @@ class Module
|
|
274
310
|
end
|
275
311
|
|
276
312
|
def remove_method(name)
|
277
|
-
|
278
|
-
var jsid = '$' + name;
|
279
|
-
var current = self.$$proto[jsid];
|
280
|
-
delete self.$$proto[jsid];
|
313
|
+
`Opal.undef(self, '$' + name)`
|
281
314
|
|
282
|
-
|
283
|
-
// Opal.retire(self, [jsid]);
|
284
|
-
return self;
|
285
|
-
}
|
315
|
+
self
|
286
316
|
end
|
287
317
|
|
288
318
|
def include(*mods)
|
@@ -304,7 +334,7 @@ class Module
|
|
304
334
|
|
305
335
|
def include?(mod)
|
306
336
|
%x{
|
307
|
-
for (var cls = self; cls; cls = cls
|
337
|
+
for (var cls = self; cls; cls = cls.$$super) {
|
308
338
|
for (var i = 0; i != cls.$$inc.length; i++) {
|
309
339
|
var mod2 = cls.$$inc[i];
|
310
340
|
if (mod === mod2) {
|
@@ -328,17 +358,17 @@ class Module
|
|
328
358
|
}
|
329
359
|
end
|
330
360
|
|
331
|
-
def instance_methods(include_super =
|
361
|
+
def instance_methods(include_super = true)
|
332
362
|
%x{
|
333
363
|
var methods = [],
|
334
364
|
proto = self.$$proto;
|
335
365
|
|
336
366
|
for (var prop in proto) {
|
337
|
-
if (!prop.charAt(0) === '$') {
|
367
|
+
if (!(prop.charAt(0) === '$')) {
|
338
368
|
continue;
|
339
369
|
}
|
340
370
|
|
341
|
-
if (typeof(proto[prop])
|
371
|
+
if (!(typeof(proto[prop]) === "function")) {
|
342
372
|
continue;
|
343
373
|
}
|
344
374
|
|
data/opal/corelib/numeric.rb
CHANGED
@@ -5,6 +5,11 @@ class Numeric
|
|
5
5
|
|
6
6
|
`def.$$is_number = true`
|
7
7
|
|
8
|
+
def __id__
|
9
|
+
`(self * 2) + 1`
|
10
|
+
end
|
11
|
+
alias object_id __id__
|
12
|
+
|
8
13
|
def coerce(other, type = :operation)
|
9
14
|
%x{
|
10
15
|
if (other.$$is_number) {
|
@@ -266,6 +271,9 @@ class Numeric
|
|
266
271
|
return enum_for :downto, finish unless block
|
267
272
|
|
268
273
|
%x{
|
274
|
+
if (!finish.$$is_number) {
|
275
|
+
#{raise ArgumentError, "comparison of #{self.class} with #{finish.class} failed"}
|
276
|
+
}
|
269
277
|
for (var i = self; i >= finish; i--) {
|
270
278
|
if (block(i) === $breaker) {
|
271
279
|
return $breaker.$v;
|
@@ -277,7 +285,10 @@ class Numeric
|
|
277
285
|
end
|
278
286
|
|
279
287
|
alias eql? ==
|
280
|
-
|
288
|
+
|
289
|
+
def equal?(other)
|
290
|
+
self == other || `isNaN(self) && isNaN(other)`
|
291
|
+
end
|
281
292
|
|
282
293
|
def even?
|
283
294
|
`self % 2 === 0`
|
@@ -455,6 +466,9 @@ class Numeric
|
|
455
466
|
return enum_for :upto, finish unless block
|
456
467
|
|
457
468
|
%x{
|
469
|
+
if (!finish.$$is_number) {
|
470
|
+
#{raise ArgumentError, "comparison of #{self.class} with #{finish.class} failed"}
|
471
|
+
}
|
458
472
|
for (var i = self; i <= finish; i++) {
|
459
473
|
if (block(i) === $breaker) {
|
460
474
|
return $breaker.$v;
|
data/opal/corelib/regexp.rb
CHANGED
@@ -35,53 +35,12 @@ class Regexp
|
|
35
35
|
`other.constructor == RegExp && self.toString() === other.toString()`
|
36
36
|
end
|
37
37
|
|
38
|
-
def ===(
|
39
|
-
|
40
|
-
if (!str.$$is_string && #{str.respond_to?(:to_str)}) {
|
41
|
-
#{str = str.to_str};
|
42
|
-
}
|
43
|
-
|
44
|
-
if (!str.$$is_string) {
|
45
|
-
return false;
|
46
|
-
}
|
47
|
-
|
48
|
-
return self.test(str);
|
49
|
-
}
|
38
|
+
def ===(string)
|
39
|
+
`#{match(string)} !== nil`
|
50
40
|
end
|
51
41
|
|
52
42
|
def =~(string)
|
53
|
-
|
54
|
-
$~ = nil
|
55
|
-
|
56
|
-
return
|
57
|
-
end
|
58
|
-
|
59
|
-
string = Opal.coerce_to(string, String, :to_str).to_s
|
60
|
-
|
61
|
-
%x{
|
62
|
-
var re = self;
|
63
|
-
|
64
|
-
if (re.global) {
|
65
|
-
// should we clear it afterwards too?
|
66
|
-
re.lastIndex = 0;
|
67
|
-
}
|
68
|
-
else {
|
69
|
-
// rewrite regular expression to add the global flag to capture pre/post match
|
70
|
-
re = new RegExp(re.source, 'g' + (re.multiline ? 'm' : '') + (re.ignoreCase ? 'i' : ''));
|
71
|
-
}
|
72
|
-
|
73
|
-
var result = re.exec(string);
|
74
|
-
|
75
|
-
if (result) {
|
76
|
-
#{$~ = MatchData.new(`re`, `result`)};
|
77
|
-
|
78
|
-
return result.index;
|
79
|
-
}
|
80
|
-
else {
|
81
|
-
#{$~ = nil};
|
82
|
-
return nil;
|
83
|
-
}
|
84
|
-
}
|
43
|
+
match(string) && $~.begin(0)
|
85
44
|
end
|
86
45
|
|
87
46
|
alias eql? ==
|
@@ -91,49 +50,46 @@ class Regexp
|
|
91
50
|
end
|
92
51
|
|
93
52
|
def match(string, pos = undefined, &block)
|
94
|
-
if `string === nil`
|
95
|
-
$~ = nil
|
96
|
-
|
97
|
-
return
|
98
|
-
end
|
99
|
-
|
100
|
-
if `string.$$is_string == null`
|
101
|
-
unless string.respond_to? :to_str
|
102
|
-
raise TypeError, "no implicit conversion of #{string.class} into String"
|
103
|
-
end
|
104
|
-
|
105
|
-
string = string.to_str
|
106
|
-
end
|
107
|
-
|
108
53
|
%x{
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
re.lastIndex = 0;
|
54
|
+
if (pos === undefined) {
|
55
|
+
pos = 0;
|
56
|
+
} else {
|
57
|
+
pos = #{Opal.coerce_to(pos, Integer, :to_int)};
|
114
58
|
}
|
115
|
-
|
116
|
-
|
59
|
+
|
60
|
+
if (string === nil) {
|
61
|
+
return #{$~ = nil};
|
117
62
|
}
|
118
63
|
|
119
|
-
|
64
|
+
string = #{Opal.coerce_to(string, String, :to_str)};
|
65
|
+
|
66
|
+
if (pos < 0) {
|
67
|
+
pos += string.length;
|
68
|
+
if (pos < 0) {
|
69
|
+
return #{$~ = nil};
|
70
|
+
}
|
71
|
+
}
|
120
72
|
|
121
|
-
|
122
|
-
result = #{$~ = MatchData.new(`re`, `result`)};
|
73
|
+
var md, re = new RegExp(self.source, 'gm' + (self.ignoreCase ? 'i' : ''));
|
123
74
|
|
124
|
-
|
125
|
-
|
75
|
+
while (true) {
|
76
|
+
md = re.exec(string);
|
77
|
+
if (md === null) {
|
78
|
+
return #{$~ = nil};
|
126
79
|
}
|
127
|
-
|
128
|
-
|
80
|
+
if (md.index >= pos) {
|
81
|
+
#{$~ = MatchData.new(`re`, `md`)}
|
82
|
+
return block === nil ? #{$~} : #{block.call($~)};
|
129
83
|
}
|
130
|
-
|
131
|
-
else {
|
132
|
-
return #{$~ = nil};
|
84
|
+
re.lastIndex = md.index + 1;
|
133
85
|
}
|
134
86
|
}
|
135
87
|
end
|
136
88
|
|
89
|
+
def ~
|
90
|
+
self =~ $_
|
91
|
+
end
|
92
|
+
|
137
93
|
def source
|
138
94
|
`self.source`
|
139
95
|
end
|