Skip to content

Commit

Permalink
Showing 5 changed files with 47 additions and 18 deletions.
19 changes: 10 additions & 9 deletions corelib/array.rb
Original file line number Diff line number Diff line change
@@ -485,19 +485,20 @@ def drop(number)
def each(&block)
return enum_for :each unless block_given?

if block.arity > 0
%x{
for (var i = 0, length = #{self}.length; i < length; i++) {
if (block.apply(null, #{self}[i]._isArray ? #{self}[i] : [#{self}[i]]) === $breaker) return $breaker.$v;
%x{
if (block.length > 1) {
for (var i = 0, length = #{self}.length, el; i < length; i++) {
el = #{self}[i];
if (!el._isArray) el = [el];
if (block.apply(null, el) === $breaker) return $breaker.$v;
}
}
else
%x{
} else {
for (var i = 0, length = #{self}.length; i < length; i++) {
#{yield `#{self}[i]`};
if (block(#{self}[i]) === $breaker) return $breaker.$v;
}
}
end
}

self
end
30 changes: 30 additions & 0 deletions corelib/runtime.js
Original file line number Diff line number Diff line change
@@ -300,6 +300,36 @@
throw Opal.returner;
};

// handles yield calls for 1 yielded arg
Opal.$yield1 = function(block, arg) {
if (typeof(block) !== "function") {
throw Opal.LocalJumpError.$new("no block given");
}

if (block.length > 1) {
if (arg._isArray) {
return block.apply(null, arg);
}
else {
return block(arg);
}
}
else {
return block(arg);
}
};

// handles yield for > 1 yielded arg
Opal.$yieldX = function(block, args) {
if (block.length > 1 && args.length == 1) {
if (args[0]._isArray) {
return block.apply(null, args[0]);
}
}

return block.apply(null, args);
};

/*
Call a ruby method on a ruby object with some arguments:
11 changes: 7 additions & 4 deletions lib/opal/parser.rb
Original file line number Diff line number Diff line change
@@ -1872,15 +1872,18 @@ def handle_yield_call(sexp, level)
@scope.uses_block!

splat = sexp.any? { |s| s.first == :splat }
sexp.unshift s(:js_tmp, 'null') unless splat # self
args = process_arglist sexp, level

if !splat and sexp.size == 1
return [f("$opal.$yield1(#{@scope.block_name || '$yield'}, "), process(sexp[0]), f(")")]
end

args = process_arglist sexp, level
y = @scope.block_name || '$yield'

if splat
[f("#{y}.apply(null, ", sexp), args, f(")", sexp)]
[f("$opal.$yieldX(#{y}, ", sexp), args, f(")")]
else
[f("#{y}.call(", sexp), args, f(")", sexp)]
[f("$opal.$yieldX(#{y}, [", sexp), args, f("])")]
end
end

3 changes: 0 additions & 3 deletions spec/filters/bugs/block_args.rb

This file was deleted.

2 changes: 0 additions & 2 deletions spec/filters/bugs/language/block.rb
Original file line number Diff line number Diff line change
@@ -3,6 +3,4 @@
fails "A block arguments with _ extracts arguments with _"
fails "A block taking |*a| arguments does not call #to_ary to convert a single yielded object to an Array"
fails "A block taking |*| arguments does not call #to_ary to convert a single yielded object to an Array"
fails "A block taking |a, *b| arguments destructures a splatted Array"
fails "A block taking |a, b| arguments destructures a splatted Array"
end

2 comments on commit e87b43e

@adambeynon
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@meh work in progress. 3 specs fixed so far. Runtime helpers seem to be a cleaner way to do it.

@meh
Copy link
Member

@meh meh commented on e87b43e Aug 9, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐼

Please sign in to comment.