Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions scripts/conformance/rubyspec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ class SpecContext
attr_reader :desc, :examples, :before_each, :after_each, :before_all
def initialize(desc, parent)
@desc = desc
@parent = parent
@examples = []
@before_each = parent ? parent.before_each.dup : []
@after_each = parent ? parent.after_each.dup : []
Expand All @@ -556,6 +557,19 @@ def before(scope = :each, &blk)
def after(scope = :each, &blk); @after_each << blk if scope == :each; end
def describe(d, *a, &blk)
child = SpecContext.new("#{@desc} #{d}", self)
# Carry helpers written with `def` in THIS block down to the child. The block
# is instance_eval'd, so a `def` lands on this object's singleton, and a
# nested describe runs on a different object — which is how
# core/string/valid_encoding/utf_8_spec lost all 28 of its examples: they call
# an outer `def utf8`. Forward each EXISTING helper explicitly rather than
# adding a method_missing, because a genuinely missing method must still raise
# from the caller with no shim frame in the backtrace — language/send_spec
# asserts precisely that, and a method_missing here broke it.
parent = self
sc = singleton_class
(sc.instance_methods(false) + sc.private_instance_methods(false)).each do |m|
child.define_singleton_method(m) { |*ar, &bl| parent.send(m, *ar, &bl) }
end
$ctx_stack.push(child)
begin
child.instance_eval(&blk) if blk
Expand Down
Loading