Skip to content

Commit

Permalink
Call #instance_exec on DSL object instead of proxy (#39)
Browse files Browse the repository at this point in the history
when the DSL object is the same object as the block context object.

This short-circuits prior to performing setup (like copying ivars
from the block context to the proxy) that is unnecessary when the block
context and DSL object "match".

Add test that runs non-mutative code on frozen DSL object to check that
no FrozenError is raised, as it would have been if a
FallbackContextProxy tried to dynamically add methods to the DSL object.
  • Loading branch information
tomeon authored Jan 13, 2021
1 parent 1b8676b commit 19c62d0
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 1 deletion.
4 changes: 3 additions & 1 deletion HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

## [Unreleased changes](http://github.com/ms-ati/docile/compare/v1.3.5...master)

...
- Short-circuit to calling #instance_exec directly on the DSL object (prior to
constructing a proxy object) when the DSL object and block context object are
identical

## [v1.3.5 (Jan 13, 2021)](http://github.com/ms-ati/docile/compare/v1.3.4...v1.3.5)

Expand Down
7 changes: 7 additions & 0 deletions lib/docile/execution.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ module Execution
# @return [Object] the return value of the block
def exec_in_proxy_context(dsl, proxy_type, *args, &block)
block_context = eval("self", block.binding)

# Use #equal? to test strict object identity (assuming that this dictum
# from the Ruby docs holds: "[u]nlike ==, the equal? method should never
# be overridden by subclasses as it is used to determine object
# identity")
return dsl.instance_exec(*args, &block) if dsl.equal?(block_context)

proxy_context = proxy_type.new(dsl, block_context)
begin
block_context.instance_variables.each do |ivar|
Expand Down
6 changes: 6 additions & 0 deletions spec/docile_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,12 @@ def dsl_eval_string(string)
expect(dsl.foo).to eq(0)
expect(dsl.bar).to eq(1)
end

context "when the DSL object is frozen" do
it "can call non-mutative code without raising an exception" do
expect { dsl.freeze.dsl_eval_string('1 + 2') }.not_to raise_error
end
end
end

context "when NoMethodError is raised" do
Expand Down

0 comments on commit 19c62d0

Please sign in to comment.