Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1fd82ea61805
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 6b5244093b05
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Mar 15, 2016

  1. Copy the full SHA
    d708499 View commit details
  2. Copy the full SHA
    6b52440 View commit details
Showing with 27 additions and 6 deletions.
  1. +20 −0 spec/ruby/language/class_variable_spec.rb
  2. +7 −6 truffle/src/main/java/org/jruby/truffle/core/module/ModuleOperations.java
20 changes: 20 additions & 0 deletions spec/ruby/language/class_variable_spec.rb
Original file line number Diff line number Diff line change
@@ -62,3 +62,23 @@
ClassVariablesSpec::ModuleO.class_variable_defined?(:@@cvar_n).should be_false
end
end

describe 'A class variable definition' do
it "is created in a module if any of the parents do not define it" do
a = Class.new
b = Class.new(a)
c = Class.new(b)
b.class_variable_set(:@@cv, :value)

lambda { a.class_variable_get(:@@cv) }.should raise_error(NameError)
b.class_variable_get(:@@cv).should == :value
c.class_variable_get(:@@cv).should == :value

# updates the same variable
c.class_variable_set(:@@cv, :next)

lambda { a.class_variable_get(:@@cv) }.should raise_error(NameError)
b.class_variable_get(:@@cv).should == :next
c.class_variable_get(:@@cv).should == :next
end
end
Original file line number Diff line number Diff line change
@@ -362,27 +362,28 @@ public static void setClassVariable(final RubyContext context, DynamicObject mod

// if the cvar is not already defined we need to take lock and ensure there is only one
// defined in the class tree
if (trySetClassVariable(module, name, value) == null) {
if (!trySetClassVariable(module, name, value)) {
synchronized (context.getClassVariableDefinitionLock()) {
if (trySetClassVariable(module, name, value) == null) {
if (!trySetClassVariable(module, name, value)) {
moduleFields.getClassVariables().put(name, value);
}
}
}
}

private static DynamicObject trySetClassVariable(DynamicObject module, final String name, final Object value) {
final ModuleFields moduleFields = Layouts.MODULE.getFields(module);
return classVariableLookup(module, new Function1<DynamicObject, DynamicObject>() {
private static boolean trySetClassVariable(DynamicObject topModule, final String name, final Object value) {
final DynamicObject found = classVariableLookup(topModule, new Function1<DynamicObject, DynamicObject>() {
@Override
public DynamicObject apply(DynamicObject module) {
if (moduleFields.getClassVariables().putIfAbsent(name, value) == null) {
final ModuleFields moduleFields = Layouts.MODULE.getFields(module);
if (moduleFields.getClassVariables().replace(name, value) != null) {
return module;
} else {
return null;
}
}
});
return found != null;
}

@TruffleBoundary