opal 0.7.0.beta1 → 0.7.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.gitmodules +1 -1
- data/.inch.yml +19 -0
- data/.travis.yml +10 -7
- data/CHANGELOG.md +23 -0
- data/README.md +2 -2
- data/Rakefile +43 -1
- data/bin/opal +6 -1
- data/lib/mspec/opal/rake_task.rb +10 -31
- data/lib/mspec/opal/runner.rb +44 -1
- data/lib/mspec/opal/special_calls.rb +25 -0
- data/lib/opal/builder.rb +1 -1
- data/lib/opal/builder_processors.rb +4 -23
- data/lib/opal/cli.rb +17 -11
- data/lib/opal/cli_options.rb +1 -1
- data/lib/opal/cli_runners.rb +1 -0
- data/lib/opal/cli_runners/apple_script.rb +65 -0
- data/lib/opal/cli_runners/nodejs.rb +9 -3
- data/lib/opal/cli_runners/phantomjs.rb +2 -2
- data/lib/opal/cli_runners/server.rb +7 -5
- data/lib/opal/compiler.rb +1 -1
- data/lib/opal/nodes/call.rb +3 -2
- data/lib/opal/nodes/constants.rb +3 -3
- data/lib/opal/nodes/def.rb +7 -7
- data/lib/opal/nodes/defined.rb +2 -2
- data/lib/opal/nodes/definitions.rb +1 -1
- data/lib/opal/nodes/literal.rb +1 -1
- data/lib/opal/nodes/logic.rb +1 -1
- data/lib/opal/nodes/masgn.rb +1 -1
- data/lib/opal/nodes/module.rb +1 -1
- data/lib/opal/nodes/rescue.rb +1 -1
- data/lib/opal/nodes/scope.rb +1 -1
- data/lib/opal/nodes/super.rb +3 -3
- data/lib/opal/nodes/top.rb +11 -9
- data/lib/opal/nodes/variables.rb +39 -6
- data/lib/opal/nodes/yield.rb +3 -3
- data/lib/opal/parser.rb +3 -1
- data/lib/opal/parser/lexer.rb +8 -2
- data/lib/opal/paths.rb +13 -3
- data/lib/opal/sprockets/server.rb +1 -1
- data/lib/opal/version.rb +1 -1
- data/opal.gemspec +1 -1
- data/opal/corelib/array.rb +29 -20
- data/opal/corelib/array/inheritance.rb +3 -3
- data/opal/corelib/basic_object.rb +3 -1
- data/opal/corelib/class.rb +1 -1
- data/opal/corelib/comparable.rb +6 -5
- data/opal/corelib/dir.rb +4 -4
- data/opal/corelib/enumerable.rb +25 -25
- data/opal/corelib/enumerator.rb +16 -14
- data/opal/corelib/error.rb +13 -4
- data/opal/corelib/hash.rb +511 -162
- data/opal/corelib/helpers.rb +1 -1
- data/opal/corelib/kernel.rb +60 -44
- data/opal/corelib/match_data.rb +1 -10
- data/opal/corelib/method.rb +1 -1
- data/opal/corelib/module.rb +62 -32
- data/opal/corelib/nil_class.rb +1 -6
- data/opal/corelib/numeric.rb +6 -3
- data/opal/corelib/proc.rb +1 -1
- data/opal/corelib/regexp.rb +15 -6
- data/opal/corelib/runtime.js +57 -36
- data/opal/corelib/string.rb +38 -2
- data/opal/corelib/string/inheritance.rb +3 -3
- data/opal/corelib/struct.rb +1 -1
- data/opal/corelib/time.rb +46 -3
- data/spec/filters/bugs/date.rb +15 -0
- data/spec/filters/bugs/enumerator.rb +7 -0
- data/spec/filters/bugs/exception.rb +12 -0
- data/spec/filters/bugs/hash.rb +0 -18
- data/spec/filters/bugs/match_data.rb +13 -0
- data/spec/filters/bugs/module.rb +13 -0
- data/spec/filters/bugs/numeric.rb +2 -0
- data/spec/filters/bugs/regexp.rb +0 -2
- data/spec/filters/bugs/stringscanner.rb +8 -0
- data/spec/filters/bugs/time.rb +1 -1
- data/spec/filters/unsupported/float.rb +1 -0
- data/spec/filters/unsupported/symbols.rb +10 -0
- data/spec/filters/unsupported/tainted.rb +3 -0
- data/spec/filters/unsupported/trusted.rb +3 -0
- data/spec/lib/compiler_spec.rb +2 -2
- data/spec/lib/parser/call_spec.rb +7 -0
- data/spec/opal/core/date_spec.rb +49 -8
- data/spec/opal/core/exception_spec.rb +13 -0
- data/spec/opal/core/fixtures/require_tree_files/nested/nested 1.rb +1 -0
- data/spec/opal/core/fixtures/require_tree_files/nested/nested 2.rb +1 -0
- data/spec/opal/core/fixtures/require_tree_files/other/other 1.rb +1 -0
- data/spec/opal/core/kernel/require_tree_spec.rb +3 -1
- data/spec/opal/core/language/predefined_spec.rb +43 -0
- data/spec/opal/stdlib/promise/rescue_spec.rb +9 -0
- data/spec/opal/stdlib/promise/then_spec.rb +9 -0
- data/spec/opal/stdlib/promise/trace_spec.rb +9 -0
- data/spec/rubyspecs +40 -19
- data/spec/spec_helper.rb +10 -5
- data/stdlib/date.rb +68 -8
- data/stdlib/fileutils.rb +0 -0
- data/stdlib/iconv.rb +0 -0
- data/stdlib/json.rb +16 -3
- data/stdlib/native.rb +36 -17
- data/stdlib/nodejs.rb +3 -0
- data/stdlib/nodejs/dir.rb +1 -1
- data/stdlib/nodejs/file.rb +2 -2
- data/stdlib/nodejs/io.rb +1 -1
- data/stdlib/nodejs/process.rb +2 -2
- data/stdlib/nodejs/require.rb +5 -7
- data/stdlib/nodejs/runtime.rb +3 -2
- data/stdlib/pathname.rb +25 -1
- data/stdlib/promise.rb +16 -0
- data/stdlib/set.rb +48 -4
- data/stdlib/strscan.rb +12 -1
- data/stdlib/yaml.rb +1 -0
- metadata +27 -7
- data/spec/opal/core/language/symbol_spec.rb +0 -40
data/opal/corelib/enumerator.rb
CHANGED
@@ -59,7 +59,7 @@ class Enumerator
|
|
59
59
|
return enum_for :with_index, offset unless block
|
60
60
|
|
61
61
|
%x{
|
62
|
-
var result
|
62
|
+
var result, index = 0;
|
63
63
|
|
64
64
|
self.$each.$$p = function() {
|
65
65
|
var param = #{Opal.destructure(`arguments`)},
|
@@ -78,13 +78,15 @@ class Enumerator
|
|
78
78
|
if (result !== undefined) {
|
79
79
|
return result;
|
80
80
|
}
|
81
|
+
|
82
|
+
return nil;
|
81
83
|
}
|
82
84
|
end
|
83
85
|
|
84
86
|
alias with_object each_with_object
|
85
87
|
|
86
88
|
def inspect
|
87
|
-
result = "#<#{self.class
|
89
|
+
result = "#<#{self.class}: #{@object.inspect}:#{@method}"
|
88
90
|
|
89
91
|
unless @args.empty?
|
90
92
|
result += "(#{@args.inspect[Range.new(1, -2)]})"
|
@@ -109,7 +111,7 @@ class Enumerator
|
|
109
111
|
try {
|
110
112
|
args.unshift(#{yielder});
|
111
113
|
|
112
|
-
if (
|
114
|
+
if (Opal.yieldX(#@block, args) === $breaker) {
|
113
115
|
return $breaker.$v;
|
114
116
|
}
|
115
117
|
}
|
@@ -134,7 +136,7 @@ class Enumerator
|
|
134
136
|
|
135
137
|
def yield(*values)
|
136
138
|
%x{
|
137
|
-
var value =
|
139
|
+
var value = Opal.yieldX(#@block, values);
|
138
140
|
|
139
141
|
if (value === $breaker) {
|
140
142
|
throw $breaker;
|
@@ -167,7 +169,7 @@ class Enumerator
|
|
167
169
|
%x{
|
168
170
|
args.unshift(#{yielder});
|
169
171
|
|
170
|
-
if (
|
172
|
+
if (Opal.yieldX(block, args) === $breaker) {
|
171
173
|
return $breaker;
|
172
174
|
}
|
173
175
|
}
|
@@ -191,7 +193,7 @@ class Enumerator
|
|
191
193
|
|
192
194
|
Lazy.new(self, enumerator_size) {|enum, *args|
|
193
195
|
%x{
|
194
|
-
var value =
|
196
|
+
var value = Opal.yieldX(block, args);
|
195
197
|
|
196
198
|
if (value === $breaker) {
|
197
199
|
return $breaker;
|
@@ -209,7 +211,7 @@ class Enumerator
|
|
209
211
|
|
210
212
|
Lazy.new(self, nil) {|enum, *args|
|
211
213
|
%x{
|
212
|
-
var value =
|
214
|
+
var value = Opal.yieldX(block, args);
|
213
215
|
|
214
216
|
if (value === $breaker) {
|
215
217
|
return $breaker;
|
@@ -265,7 +267,7 @@ class Enumerator
|
|
265
267
|
Lazy.new(self, nil) {|enum, *args|
|
266
268
|
if succeeding
|
267
269
|
%x{
|
268
|
-
var value =
|
270
|
+
var value = Opal.yieldX(block, args);
|
269
271
|
|
270
272
|
if (value === $breaker) {
|
271
273
|
return $breaker;
|
@@ -294,7 +296,7 @@ class Enumerator
|
|
294
296
|
|
295
297
|
Lazy.new(self, nil) {|enum, *args|
|
296
298
|
%x{
|
297
|
-
var value =
|
299
|
+
var value = Opal.yieldX(block, args);
|
298
300
|
|
299
301
|
if (value === $breaker) {
|
300
302
|
return $breaker;
|
@@ -317,13 +319,13 @@ class Enumerator
|
|
317
319
|
value = #{pattern === `param`};
|
318
320
|
|
319
321
|
if (#{Opal.truthy?(`value`)}) {
|
320
|
-
value =
|
322
|
+
value = Opal.yield1(block, param);
|
321
323
|
|
322
324
|
if (value === $breaker) {
|
323
325
|
return $breaker;
|
324
326
|
}
|
325
327
|
|
326
|
-
#{enum.yield
|
328
|
+
#{enum.yield `Opal.yield1(block, param)`};
|
327
329
|
}
|
328
330
|
}
|
329
331
|
}
|
@@ -352,7 +354,7 @@ class Enumerator
|
|
352
354
|
|
353
355
|
Lazy.new(self, nil) {|enum, *args|
|
354
356
|
%x{
|
355
|
-
var value =
|
357
|
+
var value = Opal.yieldX(block, args);
|
356
358
|
|
357
359
|
if (value === $breaker) {
|
358
360
|
return $breaker;
|
@@ -397,7 +399,7 @@ class Enumerator
|
|
397
399
|
|
398
400
|
Lazy.new(self, nil) {|enum, *args|
|
399
401
|
%x{
|
400
|
-
var value =
|
402
|
+
var value = Opal.yieldX(block, args);
|
401
403
|
|
402
404
|
if (value === $breaker) {
|
403
405
|
return $breaker;
|
@@ -416,7 +418,7 @@ class Enumerator
|
|
416
418
|
alias to_enum enum_for
|
417
419
|
|
418
420
|
def inspect
|
419
|
-
"#<#{self.class
|
421
|
+
"#<#{self.class}: #{@enumerator.inspect}>"
|
420
422
|
end
|
421
423
|
end
|
422
424
|
end
|
data/opal/corelib/error.rb
CHANGED
@@ -1,15 +1,24 @@
|
|
1
1
|
class Exception
|
2
2
|
attr_reader :message
|
3
3
|
|
4
|
-
def self.new(message = '')
|
4
|
+
def self.new(message = 'Exception')
|
5
5
|
%x{
|
6
|
-
var err = new
|
7
|
-
|
6
|
+
var err = new self.$$alloc(message);
|
7
|
+
|
8
|
+
if (Error.captureStackTrace) {
|
9
|
+
Error.captureStackTrace(err);
|
10
|
+
}
|
11
|
+
|
8
12
|
err.name = self.$$name;
|
13
|
+
err.$initialize(message);
|
9
14
|
return err;
|
10
15
|
}
|
11
16
|
end
|
12
17
|
|
18
|
+
def initialize(message)
|
19
|
+
`self.message = message`
|
20
|
+
end
|
21
|
+
|
13
22
|
def backtrace
|
14
23
|
%x{
|
15
24
|
var backtrace = self.stack;
|
@@ -26,7 +35,7 @@ class Exception
|
|
26
35
|
end
|
27
36
|
|
28
37
|
def inspect
|
29
|
-
"#<#{self.class
|
38
|
+
"#<#{self.class}: '#@message'>"
|
30
39
|
end
|
31
40
|
|
32
41
|
alias to_s message
|
data/opal/corelib/hash.rb
CHANGED
@@ -4,7 +4,7 @@ class Hash
|
|
4
4
|
include Enumerable
|
5
5
|
|
6
6
|
def self.[](*objs)
|
7
|
-
|
7
|
+
`Opal.hash.apply(null, objs)`
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.allocate
|
@@ -12,6 +12,7 @@ class Hash
|
|
12
12
|
var hash = new self.$$alloc;
|
13
13
|
|
14
14
|
hash.map = {};
|
15
|
+
hash.smap = {};
|
15
16
|
hash.keys = [];
|
16
17
|
hash.none = nil;
|
17
18
|
hash.proc = nil;
|
@@ -34,7 +35,7 @@ class Hash
|
|
34
35
|
return true;
|
35
36
|
}
|
36
37
|
|
37
|
-
if (!other.
|
38
|
+
if (!other.keys || !other.smap || !other.map) {
|
38
39
|
return false;
|
39
40
|
}
|
40
41
|
|
@@ -42,12 +43,30 @@ class Hash
|
|
42
43
|
return false;
|
43
44
|
}
|
44
45
|
|
45
|
-
var
|
46
|
-
|
46
|
+
var _map = self.map,
|
47
|
+
smap = self.smap,
|
48
|
+
_map2 = other.map,
|
49
|
+
smap2 = other.smap,
|
50
|
+
map, map2, key, khash, value, value2;
|
47
51
|
|
48
52
|
for (var i = 0, length = self.keys.length; i < length; i++) {
|
49
|
-
|
50
|
-
|
53
|
+
key = self.keys[i];
|
54
|
+
|
55
|
+
if (key.$$is_string) {
|
56
|
+
khash = key;
|
57
|
+
map = smap;
|
58
|
+
map2 = smap2;
|
59
|
+
} else {
|
60
|
+
khash = key.$hash();
|
61
|
+
map = _map;
|
62
|
+
map2 = _map2;
|
63
|
+
}
|
64
|
+
|
65
|
+
value = map[khash];
|
66
|
+
if (value === undefined) console.log('==', key, self);
|
67
|
+
value2 = map2[khash];
|
68
|
+
|
69
|
+
if (value2 === undefined || #{not(`value` == `value2`)}) {
|
51
70
|
return false;
|
52
71
|
}
|
53
72
|
}
|
@@ -58,10 +77,21 @@ class Hash
|
|
58
77
|
|
59
78
|
def [](key)
|
60
79
|
%x{
|
61
|
-
var map
|
80
|
+
var map, khash;
|
81
|
+
|
82
|
+
if (key.$$is_string) {
|
83
|
+
map = self.smap;
|
84
|
+
khash = key;
|
85
|
+
} else {
|
86
|
+
map = self.map;
|
87
|
+
khash = key.$hash();
|
88
|
+
}
|
62
89
|
|
63
|
-
if (
|
64
|
-
|
90
|
+
if (map === undefined) { console.log(self, '[] --> key:', key, khash, map) }
|
91
|
+
|
92
|
+
|
93
|
+
if (Opal.hasOwnProperty.call(map, khash)) {
|
94
|
+
return map[khash];
|
65
95
|
}
|
66
96
|
|
67
97
|
var proc = #@proc;
|
@@ -76,13 +106,21 @@ class Hash
|
|
76
106
|
|
77
107
|
def []=(key, value)
|
78
108
|
%x{
|
79
|
-
var map
|
109
|
+
var map, khash, value;
|
110
|
+
|
111
|
+
if (key.$$is_string) {
|
112
|
+
map = self.smap;
|
113
|
+
khash = key;
|
114
|
+
} else {
|
115
|
+
map = self.map;
|
116
|
+
khash = key.$hash();
|
117
|
+
}
|
80
118
|
|
81
|
-
if (
|
119
|
+
if (!Opal.hasOwnProperty.call(map, khash)) {
|
82
120
|
self.keys.push(key);
|
83
121
|
}
|
84
122
|
|
85
|
-
map[
|
123
|
+
map[khash] = value;
|
86
124
|
|
87
125
|
return value;
|
88
126
|
}
|
@@ -90,13 +128,22 @@ class Hash
|
|
90
128
|
|
91
129
|
def assoc(object)
|
92
130
|
%x{
|
93
|
-
var keys = self.keys,
|
131
|
+
var keys = self.keys,
|
132
|
+
map, key, khash;
|
94
133
|
|
95
134
|
for (var i = 0, length = keys.length; i < length; i++) {
|
96
135
|
key = keys[i];
|
97
136
|
|
98
137
|
if (#{`key` == object}) {
|
99
|
-
|
138
|
+
if (key.$$is_string) {
|
139
|
+
map = self.smap;
|
140
|
+
khash = key;
|
141
|
+
} else {
|
142
|
+
map = self.map;
|
143
|
+
khash = key.$hash();
|
144
|
+
}
|
145
|
+
|
146
|
+
return [key, map[khash]];
|
100
147
|
}
|
101
148
|
}
|
102
149
|
|
@@ -107,6 +154,7 @@ class Hash
|
|
107
154
|
def clear
|
108
155
|
%x{
|
109
156
|
self.map = {};
|
157
|
+
self.smap = {};
|
110
158
|
self.keys = [];
|
111
159
|
return self;
|
112
160
|
}
|
@@ -114,25 +162,41 @@ class Hash
|
|
114
162
|
|
115
163
|
def clone
|
116
164
|
%x{
|
117
|
-
var
|
118
|
-
|
165
|
+
var _map = {},
|
166
|
+
smap = {},
|
167
|
+
_map2 = self.map,
|
168
|
+
smap2 = self.smap,
|
169
|
+
keys = [],
|
170
|
+
map, map2, key, khash, value;
|
119
171
|
|
120
172
|
for (var i = 0, length = self.keys.length; i < length; i++) {
|
121
|
-
|
122
|
-
|
173
|
+
key = self.keys[i];
|
174
|
+
|
175
|
+
if (key.$$is_string) {
|
176
|
+
khash = key;
|
177
|
+
map = smap;
|
178
|
+
map2 = smap2;
|
179
|
+
} else {
|
180
|
+
khash = key.$hash();
|
181
|
+
map = _map;
|
182
|
+
map2 = _map2;
|
183
|
+
}
|
184
|
+
|
185
|
+
value = map2[khash];
|
123
186
|
|
124
187
|
keys.push(key);
|
125
|
-
map[
|
188
|
+
map[khash] = value;
|
126
189
|
}
|
127
190
|
|
128
|
-
var
|
191
|
+
var clone = new self.$$class.$$alloc();
|
129
192
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
193
|
+
clone.map = _map;
|
194
|
+
clone.smap = smap;
|
195
|
+
clone.keys = keys;
|
196
|
+
clone.none = self.none;
|
197
|
+
clone.proc = self.proc;
|
134
198
|
|
135
|
-
return
|
199
|
+
return clone;
|
136
200
|
}
|
137
201
|
end
|
138
202
|
|
@@ -172,10 +236,20 @@ class Hash
|
|
172
236
|
|
173
237
|
def delete(key, &block)
|
174
238
|
%x{
|
175
|
-
var
|
239
|
+
var result, map, khash;
|
240
|
+
|
241
|
+
if (key.$$is_string) {
|
242
|
+
map = self.smap;
|
243
|
+
khash = key;
|
244
|
+
} else {
|
245
|
+
map = self.map;
|
246
|
+
khash = key.$hash();
|
247
|
+
}
|
248
|
+
|
249
|
+
result = map[khash];
|
176
250
|
|
177
251
|
if (result != null) {
|
178
|
-
delete map[
|
252
|
+
delete map[khash];
|
179
253
|
self.keys.$delete(key);
|
180
254
|
|
181
255
|
return result;
|
@@ -192,18 +266,31 @@ class Hash
|
|
192
266
|
return enum_for :delete_if unless block
|
193
267
|
|
194
268
|
%x{
|
195
|
-
var
|
269
|
+
var _map = self.map,
|
270
|
+
smap = self.smap,
|
271
|
+
keys = self.keys,
|
272
|
+
map, key, value, obj, khash;
|
196
273
|
|
197
274
|
for (var i = 0, length = keys.length; i < length; i++) {
|
198
|
-
|
275
|
+
key = keys[i];
|
199
276
|
|
200
|
-
if (
|
277
|
+
if (key.$$is_string) {
|
278
|
+
map = smap;
|
279
|
+
khash = key;
|
280
|
+
} else {
|
281
|
+
map = _map;
|
282
|
+
khash = key.$hash();
|
283
|
+
}
|
284
|
+
obj = map[khash];
|
285
|
+
value = block(key, obj);
|
286
|
+
|
287
|
+
if (value === $breaker) {
|
201
288
|
return $breaker.$v;
|
202
289
|
}
|
203
290
|
|
204
291
|
if (value !== false && value !== nil) {
|
205
292
|
keys.splice(i, 1);
|
206
|
-
delete map[
|
293
|
+
delete map[khash];
|
207
294
|
|
208
295
|
length--;
|
209
296
|
i--;
|
@@ -220,12 +307,23 @@ class Hash
|
|
220
307
|
return enum_for :each unless block
|
221
308
|
|
222
309
|
%x{
|
223
|
-
var
|
224
|
-
|
310
|
+
var _map = self.map,
|
311
|
+
smap = self.smap,
|
312
|
+
keys = self.keys,
|
313
|
+
map, key, khash, value;
|
225
314
|
|
226
315
|
for (var i = 0, length = keys.length; i < length; i++) {
|
227
|
-
|
228
|
-
|
316
|
+
key = keys[i];
|
317
|
+
|
318
|
+
if (key.$$is_string) {
|
319
|
+
map = smap;
|
320
|
+
khash = key;
|
321
|
+
} else {
|
322
|
+
map = _map;
|
323
|
+
khash = key.$hash();
|
324
|
+
}
|
325
|
+
|
326
|
+
value = Opal.yield1(block, [key, map[khash]]);
|
229
327
|
|
230
328
|
if (value === $breaker) {
|
231
329
|
return $breaker.$v;
|
@@ -238,12 +336,12 @@ class Hash
|
|
238
336
|
|
239
337
|
def each_key(&block)
|
240
338
|
return enum_for :each_key unless block
|
241
|
-
|
339
|
+
# @keys.each(&block)
|
242
340
|
%x{
|
243
|
-
var keys = self.keys;
|
341
|
+
var keys = self.keys, key;
|
244
342
|
|
245
343
|
for (var i = 0, length = keys.length; i < length; i++) {
|
246
|
-
|
344
|
+
key = keys[i];
|
247
345
|
|
248
346
|
if (block(key) === $breaker) {
|
249
347
|
return $breaker.$v;
|
@@ -260,10 +358,22 @@ class Hash
|
|
260
358
|
return enum_for :each_value unless block
|
261
359
|
|
262
360
|
%x{
|
263
|
-
var
|
361
|
+
var _map = self.map,
|
362
|
+
smap = self.smap,
|
363
|
+
keys = self.keys;
|
264
364
|
|
265
365
|
for (var i = 0, length = keys.length; i < length; i++) {
|
266
|
-
|
366
|
+
key = keys[i];
|
367
|
+
|
368
|
+
if (key.$$is_string) {
|
369
|
+
map = smap;
|
370
|
+
khash = key;
|
371
|
+
} else {
|
372
|
+
map = _map;
|
373
|
+
khash = key.$hash();
|
374
|
+
}
|
375
|
+
|
376
|
+
if (block(map[khash]) === $breaker) {
|
267
377
|
return $breaker.$v;
|
268
378
|
}
|
269
379
|
}
|
@@ -280,7 +390,17 @@ class Hash
|
|
280
390
|
|
281
391
|
def fetch(key, defaults = undefined, &block)
|
282
392
|
%x{
|
283
|
-
var
|
393
|
+
var map, khash, value;
|
394
|
+
|
395
|
+
if (key.$$is_string) {
|
396
|
+
khash = key;
|
397
|
+
map = self.smap;
|
398
|
+
} else {
|
399
|
+
khash = key.$hash();
|
400
|
+
map = self.map;
|
401
|
+
}
|
402
|
+
|
403
|
+
value = map[khash];
|
284
404
|
|
285
405
|
if (value != null) {
|
286
406
|
return value;
|
@@ -306,10 +426,24 @@ class Hash
|
|
306
426
|
|
307
427
|
def flatten(level=undefined)
|
308
428
|
%x{
|
309
|
-
var
|
429
|
+
var _map = self.map,
|
430
|
+
smap = self.smap,
|
431
|
+
keys = self.keys,
|
432
|
+
result = [],
|
433
|
+
map, key, khash, value;
|
310
434
|
|
311
435
|
for (var i = 0, length = keys.length; i < length; i++) {
|
312
|
-
|
436
|
+
key = keys[i];
|
437
|
+
|
438
|
+
if (key.$$is_string) {
|
439
|
+
khash = key;
|
440
|
+
map = smap;
|
441
|
+
} else {
|
442
|
+
khash = key.$hash();
|
443
|
+
map = _map;
|
444
|
+
}
|
445
|
+
|
446
|
+
value = map[khash];
|
313
447
|
|
314
448
|
result.push(key);
|
315
449
|
|
@@ -331,13 +465,34 @@ class Hash
|
|
331
465
|
end
|
332
466
|
|
333
467
|
def has_key?(key)
|
334
|
-
|
468
|
+
%x{
|
469
|
+
var keys = self.keys,
|
470
|
+
map, khash;
|
471
|
+
|
472
|
+
if (key.$$is_string) {
|
473
|
+
khash = key;
|
474
|
+
map = self.smap;
|
475
|
+
} else {
|
476
|
+
khash = key.$hash();
|
477
|
+
map = self.map;
|
478
|
+
}
|
479
|
+
|
480
|
+
if (Opal.hasOwnProperty.call(map, khash)) {
|
481
|
+
for (var i = 0, length = keys.length; i < length; i++) {
|
482
|
+
if (!#{not(key.eql?(`keys[i]`))}) {
|
483
|
+
return true;
|
484
|
+
}
|
485
|
+
}
|
486
|
+
}
|
487
|
+
|
488
|
+
return false;
|
489
|
+
}
|
335
490
|
end
|
336
491
|
|
337
492
|
def has_value?(value)
|
338
493
|
%x{
|
339
|
-
for (var
|
340
|
-
if (#{`self.map[
|
494
|
+
for (var khash in self.map) {
|
495
|
+
if (#{`self.map[khash]` == value}) {
|
341
496
|
return true;
|
342
497
|
}
|
343
498
|
}
|
@@ -346,20 +501,27 @@ class Hash
|
|
346
501
|
}
|
347
502
|
end
|
348
503
|
|
349
|
-
def hash
|
350
|
-
`self.$$id`
|
351
|
-
end
|
352
|
-
|
353
504
|
alias include? has_key?
|
354
505
|
|
355
506
|
def index(object)
|
356
507
|
%x{
|
357
|
-
var
|
508
|
+
var _map = self.map,
|
509
|
+
smap = self.smap,
|
510
|
+
keys = self.keys,
|
511
|
+
map, khash, key;
|
358
512
|
|
359
513
|
for (var i = 0, length = keys.length; i < length; i++) {
|
360
|
-
|
514
|
+
key = keys[i];
|
515
|
+
|
516
|
+
if (key.$$is_string) {
|
517
|
+
map = smap;
|
518
|
+
khash = key;
|
519
|
+
} else {
|
520
|
+
map = _map;
|
521
|
+
khash = key.$hash();
|
522
|
+
}
|
361
523
|
|
362
|
-
if (#{`map[
|
524
|
+
if (#{`map[khash]` == object}) {
|
363
525
|
return key;
|
364
526
|
}
|
365
527
|
}
|
@@ -370,13 +532,26 @@ class Hash
|
|
370
532
|
|
371
533
|
def indexes(*keys)
|
372
534
|
%x{
|
373
|
-
var result = [],
|
535
|
+
var result = [],
|
536
|
+
_map = self.map,
|
537
|
+
smap = self.smap,
|
538
|
+
map, key, khash, value;
|
374
539
|
|
375
540
|
for (var i = 0, length = keys.length; i < length; i++) {
|
376
|
-
|
541
|
+
key = keys[i];
|
542
|
+
|
543
|
+
if (key.$$is_string) {
|
544
|
+
khash = key;
|
545
|
+
map = smap;
|
546
|
+
} else {
|
547
|
+
khash = key.$hash();
|
548
|
+
map = _map;
|
549
|
+
}
|
550
|
+
|
551
|
+
value = map[khash];
|
377
552
|
|
378
|
-
if (
|
379
|
-
result.push(
|
553
|
+
if (value != null) {
|
554
|
+
result.push(value);
|
380
555
|
}
|
381
556
|
else {
|
382
557
|
result.push(self.none);
|
@@ -389,34 +564,80 @@ class Hash
|
|
389
564
|
|
390
565
|
alias indices indexes
|
391
566
|
|
567
|
+
`var inspect_ids = null;`
|
392
568
|
def inspect
|
393
569
|
%x{
|
394
|
-
var
|
570
|
+
var top = (inspect_ids === null);
|
571
|
+
try {
|
572
|
+
var inspect = [],
|
573
|
+
keys = self.keys
|
574
|
+
_map = self.map,
|
575
|
+
smap = self.smap,
|
576
|
+
id = #{object_id};
|
577
|
+
|
578
|
+
if (top) {
|
579
|
+
inspect_ids = {}
|
580
|
+
}
|
395
581
|
|
396
|
-
|
397
|
-
|
582
|
+
if (inspect_ids.hasOwnProperty(id)) {
|
583
|
+
return '{...}';
|
584
|
+
}
|
398
585
|
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
586
|
+
inspect_ids[id] = true;
|
587
|
+
|
588
|
+
for (var i = 0, length = keys.length; i < length; i++) {
|
589
|
+
var key = keys[i],
|
590
|
+
value = key.$$is_string ? smap[key] : _map[key.$hash()];
|
591
|
+
|
592
|
+
value = value;
|
593
|
+
key = key;
|
594
|
+
inspect.push(key.$inspect() + '=>' + value.$inspect());
|
403
595
|
}
|
404
|
-
}
|
405
596
|
|
406
|
-
|
597
|
+
return '{' + inspect.join(', ') + '}';
|
598
|
+
} finally {
|
599
|
+
|
600
|
+
if (top) {
|
601
|
+
inspect_ids = null;
|
602
|
+
}
|
603
|
+
}
|
407
604
|
}
|
408
605
|
end
|
409
606
|
|
410
607
|
def invert
|
411
608
|
%x{
|
412
|
-
var result =
|
413
|
-
|
609
|
+
var result = Opal.hash(),
|
610
|
+
keys = self.keys,
|
611
|
+
_map = self.map,
|
612
|
+
smap = self.smap,
|
613
|
+
keys2 = result.keys,
|
614
|
+
_map2 = result.map,
|
615
|
+
smap2 = result.smap,
|
616
|
+
map, map2, key, khash, value;
|
414
617
|
|
415
618
|
for (var i = 0, length = keys.length; i < length; i++) {
|
416
|
-
|
619
|
+
key = keys[i];
|
620
|
+
|
621
|
+
if (key.$$is_string) {
|
622
|
+
map = smap;
|
623
|
+
khash = key;
|
624
|
+
} else {
|
625
|
+
map = _map;
|
626
|
+
khash = key.$hash();
|
627
|
+
}
|
628
|
+
|
629
|
+
value = map[khash];
|
630
|
+
keys2.push(value);
|
631
|
+
|
632
|
+
if (value.$$is_string) {
|
633
|
+
map2 = smap2;
|
634
|
+
khash = value;
|
635
|
+
} else {
|
636
|
+
map2 = _map2;
|
637
|
+
khash = value.$hash();
|
638
|
+
}
|
417
639
|
|
418
|
-
|
419
|
-
map2[obj] = key;
|
640
|
+
map2[khash] = key;
|
420
641
|
}
|
421
642
|
|
422
643
|
return result;
|
@@ -427,18 +648,32 @@ class Hash
|
|
427
648
|
return enum_for :keep_if unless block
|
428
649
|
|
429
650
|
%x{
|
430
|
-
var
|
651
|
+
var _map = self.map,
|
652
|
+
smap = self.smap,
|
653
|
+
keys = self.keys,
|
654
|
+
map, key, khash, value, keep;
|
431
655
|
|
432
656
|
for (var i = 0, length = keys.length; i < length; i++) {
|
433
|
-
|
657
|
+
key = keys[i];
|
434
658
|
|
435
|
-
if (
|
659
|
+
if (key.$$is_string) {
|
660
|
+
khash = key;
|
661
|
+
map = smap;
|
662
|
+
} else {
|
663
|
+
khash = key.$hash();
|
664
|
+
map = _map;
|
665
|
+
}
|
666
|
+
|
667
|
+
value = map[khash];
|
668
|
+
keep = block(key, value);
|
669
|
+
|
670
|
+
if (keep === $breaker) {
|
436
671
|
return $breaker.$v;
|
437
672
|
}
|
438
673
|
|
439
|
-
if (
|
674
|
+
if (keep === false || keep === nil) {
|
440
675
|
keys.splice(i, 1);
|
441
|
-
delete map[
|
676
|
+
delete map[khash];
|
442
677
|
|
443
678
|
length--;
|
444
679
|
i--;
|
@@ -464,50 +699,13 @@ class Hash
|
|
464
699
|
alias member? has_key?
|
465
700
|
|
466
701
|
def merge(other, &block)
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
}
|
471
|
-
|
472
|
-
var keys = self.keys, map = self.map,
|
473
|
-
result = $opal.hash(), keys2 = result.keys, map2 = result.map;
|
474
|
-
|
475
|
-
for (var i = 0, length = keys.length; i < length; i++) {
|
476
|
-
var key = keys[i];
|
477
|
-
|
478
|
-
keys2.push(key);
|
479
|
-
map2[key] = map[key];
|
480
|
-
}
|
481
|
-
|
482
|
-
var keys = other.keys, map = other.map;
|
702
|
+
unless Hash === other
|
703
|
+
other = Opal.coerce_to!(other, Hash, :to_hash)
|
704
|
+
end
|
483
705
|
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
if (map2[key] == null) {
|
489
|
-
keys2.push(key);
|
490
|
-
}
|
491
|
-
|
492
|
-
map2[key] = map[key];
|
493
|
-
}
|
494
|
-
}
|
495
|
-
else {
|
496
|
-
for (var i = 0, length = keys.length; i < length; i++) {
|
497
|
-
var key = keys[i];
|
498
|
-
|
499
|
-
if (map2[key] == null) {
|
500
|
-
keys2.push(key);
|
501
|
-
map2[key] = map[key];
|
502
|
-
}
|
503
|
-
else {
|
504
|
-
map2[key] = block(key, map2[key], map[key]);
|
505
|
-
}
|
506
|
-
}
|
507
|
-
}
|
508
|
-
|
509
|
-
return result;
|
510
|
-
}
|
706
|
+
cloned = clone
|
707
|
+
cloned.merge!(other, &block)
|
708
|
+
cloned
|
511
709
|
end
|
512
710
|
|
513
711
|
def merge!(other, &block)
|
@@ -516,30 +714,58 @@ class Hash
|
|
516
714
|
other = #{Opal.coerce_to!(other, Hash, :to_hash)};
|
517
715
|
}
|
518
716
|
|
519
|
-
var keys
|
520
|
-
|
717
|
+
var keys = self.keys,
|
718
|
+
_map = self.map,
|
719
|
+
smap = self.smap,
|
720
|
+
keys2 = other.keys,
|
721
|
+
_map2 = other.map,
|
722
|
+
smap2 = other.smap,
|
723
|
+
map, map2, key, khash, value, value2;
|
521
724
|
|
522
725
|
if (block === nil) {
|
523
726
|
for (var i = 0, length = keys2.length; i < length; i++) {
|
524
|
-
|
727
|
+
key = keys2[i];
|
728
|
+
|
729
|
+
if (key.$$is_string) {
|
730
|
+
khash = key;
|
731
|
+
map = smap;
|
732
|
+
map2 = smap2;
|
733
|
+
} else {
|
734
|
+
khash = key.$hash();
|
735
|
+
map = _map;
|
736
|
+
map2 = _map2;
|
737
|
+
}
|
525
738
|
|
526
|
-
if (map[
|
739
|
+
if (map[khash] == null) {
|
527
740
|
keys.push(key);
|
528
741
|
}
|
529
742
|
|
530
|
-
map[
|
743
|
+
map[khash] = map2[khash];
|
531
744
|
}
|
532
745
|
}
|
533
746
|
else {
|
534
747
|
for (var i = 0, length = keys2.length; i < length; i++) {
|
535
|
-
|
748
|
+
key = keys2[i];
|
749
|
+
|
750
|
+
if (key.$$is_string) {
|
751
|
+
khash = key;
|
752
|
+
map = smap;
|
753
|
+
map2 = smap2;
|
754
|
+
} else {
|
755
|
+
khash = key.$hash();
|
756
|
+
map = _map;
|
757
|
+
map2 = _map2;
|
758
|
+
}
|
536
759
|
|
537
|
-
|
760
|
+
value = map[khash];
|
761
|
+
value2 = map2[khash];
|
762
|
+
|
763
|
+
if (value == null) {
|
538
764
|
keys.push(key);
|
539
|
-
map[
|
765
|
+
map[khash] = value2;
|
540
766
|
}
|
541
767
|
else {
|
542
|
-
map[
|
768
|
+
map[khash] = block(key, value, value2);
|
543
769
|
}
|
544
770
|
}
|
545
771
|
}
|
@@ -550,13 +776,26 @@ class Hash
|
|
550
776
|
|
551
777
|
def rassoc(object)
|
552
778
|
%x{
|
553
|
-
var keys = self.keys,
|
779
|
+
var keys = self.keys,
|
780
|
+
_map = self.map,
|
781
|
+
smap = self.smap,
|
782
|
+
key, khash, value;
|
554
783
|
|
555
784
|
for (var i = 0, length = keys.length; i < length; i++) {
|
556
|
-
|
785
|
+
key = keys[i]
|
786
|
+
|
787
|
+
if (key.$$is_string) {
|
788
|
+
khash = key;
|
789
|
+
map = smap;
|
790
|
+
} else {
|
791
|
+
khash = key.$hash();
|
792
|
+
map = _map;
|
793
|
+
}
|
794
|
+
|
795
|
+
value = map[khash];
|
557
796
|
|
558
|
-
if (#{`
|
559
|
-
return [key,
|
797
|
+
if (#{`value` == object}) {
|
798
|
+
return [key, value];
|
560
799
|
}
|
561
800
|
}
|
562
801
|
|
@@ -568,19 +807,37 @@ class Hash
|
|
568
807
|
return enum_for :reject unless block
|
569
808
|
|
570
809
|
%x{
|
571
|
-
var keys
|
572
|
-
|
810
|
+
var keys = self.keys,
|
811
|
+
_map = self.map,
|
812
|
+
smap = self.smap,
|
813
|
+
result = Opal.hash(),
|
814
|
+
_map2 = result.map,
|
815
|
+
smap2 = result.smap,
|
816
|
+
keys2 = result.keys,
|
817
|
+
map, map2, key, khash, object, value;
|
573
818
|
|
574
819
|
for (var i = 0, length = keys.length; i < length; i++) {
|
575
|
-
|
820
|
+
key = keys[i];
|
576
821
|
|
577
|
-
if (
|
822
|
+
if (key.$$is_string) {
|
823
|
+
khash = key;
|
824
|
+
map = smap;
|
825
|
+
map2 = smap2;
|
826
|
+
} else {
|
827
|
+
khash = key.$hash();
|
828
|
+
map = _map;
|
829
|
+
map2 = _map2;
|
830
|
+
}
|
831
|
+
|
832
|
+
object = map[khash];
|
833
|
+
|
834
|
+
if ((value = block(key, object)) === $breaker) {
|
578
835
|
return $breaker.$v;
|
579
836
|
}
|
580
837
|
|
581
838
|
if (value === false || value === nil) {
|
582
839
|
keys2.push(key);
|
583
|
-
map2[
|
840
|
+
map2[khash] = object;
|
584
841
|
}
|
585
842
|
}
|
586
843
|
|
@@ -590,12 +847,28 @@ class Hash
|
|
590
847
|
|
591
848
|
def replace(other)
|
592
849
|
%x{
|
593
|
-
var
|
850
|
+
var keys = self.keys = [],
|
851
|
+
_map = self.map = {},
|
852
|
+
smap = self.smap = {},
|
853
|
+
_map2 = other.map,
|
854
|
+
smap2 = other.smap,
|
855
|
+
key, khash, map, map2;
|
594
856
|
|
595
857
|
for (var i = 0, length = other.keys.length; i < length; i++) {
|
596
|
-
|
858
|
+
key = other.keys[i];
|
859
|
+
|
860
|
+
if (key.$$is_string) {
|
861
|
+
khash = key;
|
862
|
+
map = smap;
|
863
|
+
map2 = smap2;
|
864
|
+
} else {
|
865
|
+
khash = key.$hash();
|
866
|
+
map = _map;
|
867
|
+
map2 = _map2;
|
868
|
+
}
|
869
|
+
|
597
870
|
keys.push(key);
|
598
|
-
map[
|
871
|
+
map[khash] = map2[khash];
|
599
872
|
}
|
600
873
|
|
601
874
|
return self;
|
@@ -606,19 +879,38 @@ class Hash
|
|
606
879
|
return enum_for :select unless block
|
607
880
|
|
608
881
|
%x{
|
609
|
-
var keys
|
610
|
-
|
882
|
+
var keys = self.keys,
|
883
|
+
_map = self.map,
|
884
|
+
smap = self.smap,
|
885
|
+
result = Opal.hash(),
|
886
|
+
_map2 = result.map,
|
887
|
+
smap2 = result.smap,
|
888
|
+
keys2 = result.keys,
|
889
|
+
map, map2, key, khash, value, object;
|
611
890
|
|
612
891
|
for (var i = 0, length = keys.length; i < length; i++) {
|
613
|
-
|
892
|
+
key = keys[i];
|
893
|
+
|
894
|
+
if (key.$$is_string) {
|
895
|
+
khash = key;
|
896
|
+
map = smap;
|
897
|
+
map2 = smap2;
|
898
|
+
} else {
|
899
|
+
khash = key.$hash();
|
900
|
+
map = _map;
|
901
|
+
map2 = _map2;
|
902
|
+
}
|
903
|
+
|
904
|
+
value = map[khash];
|
905
|
+
object = block(key, value);
|
614
906
|
|
615
|
-
if (
|
907
|
+
if (object === $breaker) {
|
616
908
|
return $breaker.$v;
|
617
909
|
}
|
618
910
|
|
619
|
-
if (
|
911
|
+
if (object !== false && object !== nil) {
|
620
912
|
keys2.push(key);
|
621
|
-
map2[
|
913
|
+
map2[khash] = value;
|
622
914
|
}
|
623
915
|
}
|
624
916
|
|
@@ -630,18 +922,33 @@ class Hash
|
|
630
922
|
return enum_for :select! unless block
|
631
923
|
|
632
924
|
%x{
|
633
|
-
var
|
925
|
+
var _map = self.map,
|
926
|
+
smap = self.smap,
|
927
|
+
keys = self.keys,
|
928
|
+
result = nil,
|
929
|
+
key, khash, value, object;
|
634
930
|
|
635
931
|
for (var i = 0, length = keys.length; i < length; i++) {
|
636
|
-
|
932
|
+
key = keys[i];
|
637
933
|
|
638
|
-
if (
|
934
|
+
if (key.$$is_string) {
|
935
|
+
khash = key;
|
936
|
+
map = smap;
|
937
|
+
} else {
|
938
|
+
khash = key.$hash();
|
939
|
+
map = _map;
|
940
|
+
}
|
941
|
+
|
942
|
+
value = map[khash];
|
943
|
+
object = block(key, value);
|
944
|
+
|
945
|
+
if (object === $breaker) {
|
639
946
|
return $breaker.$v;
|
640
947
|
}
|
641
948
|
|
642
|
-
if (
|
949
|
+
if (object === false || object === nil) {
|
643
950
|
keys.splice(i, 1);
|
644
|
-
delete map[
|
951
|
+
delete map[khash];
|
645
952
|
|
646
953
|
length--;
|
647
954
|
i--;
|
@@ -655,15 +962,26 @@ class Hash
|
|
655
962
|
|
656
963
|
def shift
|
657
964
|
%x{
|
658
|
-
var keys = self.keys,
|
965
|
+
var keys = self.keys,
|
966
|
+
_map = self.map,
|
967
|
+
smap = self.smap,
|
968
|
+
map, key, khash, value;
|
659
969
|
|
660
970
|
if (keys.length) {
|
661
|
-
|
971
|
+
key = keys[0];
|
972
|
+
if (key.$$is_string) {
|
973
|
+
khash = key;
|
974
|
+
map = smap;
|
975
|
+
} else {
|
976
|
+
khash = key.$hash();
|
977
|
+
map = _map;
|
978
|
+
}
|
979
|
+
value = map[khash];
|
662
980
|
|
663
|
-
delete map[
|
981
|
+
delete map[khash];
|
664
982
|
keys.splice(0, 1);
|
665
983
|
|
666
|
-
return [key,
|
984
|
+
return [key, value];
|
667
985
|
}
|
668
986
|
|
669
987
|
return nil;
|
@@ -676,11 +994,24 @@ class Hash
|
|
676
994
|
|
677
995
|
def to_a
|
678
996
|
%x{
|
679
|
-
var keys = self.keys,
|
997
|
+
var keys = self.keys,
|
998
|
+
_map = self.map,
|
999
|
+
smap = self.smap,
|
1000
|
+
result = [],
|
1001
|
+
map, key;
|
680
1002
|
|
681
1003
|
for (var i = 0, length = keys.length; i < length; i++) {
|
682
|
-
|
683
|
-
|
1004
|
+
key = keys[i];
|
1005
|
+
|
1006
|
+
if (key.$$is_string) {
|
1007
|
+
khash = key;
|
1008
|
+
map = smap;
|
1009
|
+
} else {
|
1010
|
+
khash = key.$hash();
|
1011
|
+
map = _map;
|
1012
|
+
}
|
1013
|
+
|
1014
|
+
result.push([key, map[khash]]);
|
684
1015
|
}
|
685
1016
|
|
686
1017
|
return result;
|
@@ -689,10 +1020,15 @@ class Hash
|
|
689
1020
|
|
690
1021
|
def to_h
|
691
1022
|
%x{
|
1023
|
+
if (self.$$class === Opal.Hash) {
|
1024
|
+
return self
|
1025
|
+
}
|
1026
|
+
|
692
1027
|
var hash = new Opal.Hash.$$alloc,
|
693
1028
|
cloned = #{clone};
|
694
1029
|
|
695
1030
|
hash.map = cloned.map;
|
1031
|
+
hash.smap = cloned.smap;
|
696
1032
|
hash.keys = cloned.keys;
|
697
1033
|
hash.none = cloned.none;
|
698
1034
|
hash.proc = cloned.proc;
|
@@ -715,11 +1051,24 @@ class Hash
|
|
715
1051
|
|
716
1052
|
def values
|
717
1053
|
%x{
|
718
|
-
var
|
719
|
-
|
1054
|
+
var _map = self.map,
|
1055
|
+
smap = self.smap,
|
1056
|
+
keys = self.keys,
|
1057
|
+
result = [],
|
1058
|
+
map, khash;
|
1059
|
+
|
1060
|
+
for (var i = 0, length = keys.length; i < length; i++) {
|
1061
|
+
key = keys[i];
|
1062
|
+
|
1063
|
+
if (key.$$is_string) {
|
1064
|
+
khash = key;
|
1065
|
+
map = smap;
|
1066
|
+
} else {
|
1067
|
+
khash = key.$hash();
|
1068
|
+
map = _map;
|
1069
|
+
}
|
720
1070
|
|
721
|
-
|
722
|
-
result.push(map[key]);
|
1071
|
+
result.push(map[khash]);
|
723
1072
|
}
|
724
1073
|
|
725
1074
|
return result;
|