Skip to content

Commit

Permalink
Showing 28 changed files with 307 additions and 129 deletions.
29 changes: 16 additions & 13 deletions core/src/main/java/org/jruby/embed/IsolatedScriptingContainer.java
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@

import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.osgi.framework.Bundle;

@@ -64,21 +66,22 @@ public IsolatedScriptingContainer( LocalContextScope scope,
{
super(scope, behavior, lazy);

// get the right classloader
ClassLoader cl = this.getClass().getClassLoader();
if (cl == null) cl = Thread.currentThread().getContextClassLoader();
setClassLoader( cl );

setLoadPaths( Arrays.asList( "uri:classloader:" ) );

// set the right jruby home
setHomeDirectory( "uri:classloader:" + JRUBY_HOME );

// setup the isolated GEM_PATH, i.e. without $HOME/.gem/**
runScriptlet("require 'rubygems/defaults/jruby';"
+ "Gem::Specification.reset;"
+ "Gem::Specification.add_dir 'uri:classloader:" + JRUBY_HOME + "/lib/ruby/gems/shared';"
+ "Gem::Specification.add_dir 'uri:classloader:';");
setEnvironment(null);
}

@Override
public void setEnvironment(Map environment) {
if (environment == null || !environment.containsKey("GEM_PATH")) {
Map env = environment == null ? new HashMap() : new HashMap(environment);
env.put("GEM_PATH", "");
super.setEnvironment(env);
}
else {
super.setEnvironment(environment);
}
}

public void addLoadPath( ClassLoader cl ) {
@@ -140,6 +143,6 @@ private String createUri(ClassLoader cl, String ref) {
}

private void addGemPath(String uri) {
runScriptlet( "Gem::Specification.add_dir '" + uri + "' unless Gem::Specification.dirs.member?( '" + uri + "' )" );
runScriptlet( "require 'rubygems/defaults/jruby';Gem::Specification.add_dir '" + uri + "' unless Gem::Specification.dirs.member?( '" + uri + "' )" );
}
}
Original file line number Diff line number Diff line change
@@ -194,13 +194,9 @@ public static String findJRubyHome(Object instance) {
return jrubyhome;
} else if ((jrubyhome = SafePropertyAccessor.getProperty("jruby.home")) != null) {
return jrubyhome;
} else if (Thread.currentThread().getContextClassLoader() == null ||
Thread.currentThread().getContextClassLoader().equals(SystemPropertyCatcher.class.getClassLoader())) {
} else {
return "uri:classloader://META-INF/jruby.home";
}
else {
return "classpath:/META-INF/jruby.home";
}
}

public static String findFromJar(Object instance) {
4 changes: 4 additions & 0 deletions core/src/main/java/org/jruby/truffle/TruffleBridgeImpl.java
Original file line number Diff line number Diff line change
@@ -95,6 +95,7 @@ public void init() {
CoreMethodNodeManager.addCoreMethodNodes(rubyObjectClass, TimeNodesFactory.getFactories());
CoreMethodNodeManager.addCoreMethodNodes(rubyObjectClass, TrueClassNodesFactory.getFactories());
CoreMethodNodeManager.addCoreMethodNodes(rubyObjectClass, TruffleDebugNodesFactory.getFactories());
CoreMethodNodeManager.addCoreMethodNodes(rubyObjectClass, TrufflePrimitiveNodesFactory.getFactories());
CoreMethodNodeManager.addCoreMethodNodes(rubyObjectClass, EncodingNodesFactory.getFactories());
CoreMethodNodeManager.addCoreMethodNodes(rubyObjectClass, EncodingConverterNodesFactory.getFactories());

@@ -134,6 +135,9 @@ public void init() {
// Libraries copied unmodified from MRI
loadPath.slowPush(truffleContext.makeString(new File(home, "lib/ruby/truffle/mri").toString()));

// Shims
loadPath.slowPush(truffleContext.makeString(new File(home, "lib/ruby/truffle/shims").toString()));

// Hook

if (truffleContext.getHooks() != null) {
19 changes: 17 additions & 2 deletions core/src/main/java/org/jruby/truffle/nodes/core/BindingNodes.java
Original file line number Diff line number Diff line change
@@ -53,8 +53,23 @@ public LocalVariableSetNode(LocalVariableSetNode prev) {
public Object localVariableSetNode(RubyBinding binding, RubySymbol symbol, Object value) {
notDesignedForCompilation();

final MaterializedFrame frame = binding.getFrame();
frame.setObject(frame.getFrameDescriptor().findFrameSlot(symbol.toString()), value);
MaterializedFrame frame = binding.getFrame();

while (true) {
final FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(symbol.toString());

if (frameSlot != null) {
frame.setObject(frameSlot, value);
break;
}

frame = RubyArguments.getDeclarationFrame(frame.getArguments());

if (frame == null) {
throw new UnsupportedOperationException();
}
}

return value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.nodes.core;

import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.FrameInstance;
import com.oracle.truffle.api.frame.FrameInstanceVisitor;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.runtime.DebugOperations;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBinding;
import org.jruby.util.Memo;

@CoreClass(name = "Truffle::Primitive")
public abstract class TrufflePrimitiveNodes {

@CoreMethod(names = "binding_of_caller", onSingleton = true)
public abstract static class BindingOfCallerNode extends CoreMethodNode {

public BindingOfCallerNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public BindingOfCallerNode(BindingOfCallerNode prev) {
super(prev);
}

@Specialization
public RubyBinding bindingOfCaller() {
/*
* When you use this method you're asking for the binding of the caller at the call site. When we get into
* this method, that is then the binding of the caller of the caller.
*/

notDesignedForCompilation();

final Memo<Integer> frameCount = new Memo<>(0);

final MaterializedFrame frame = Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<MaterializedFrame>() {

@Override
public MaterializedFrame visitFrame(FrameInstance frameInstance) {
if (frameCount.get() == 1) {
return frameInstance.getFrame(FrameInstance.FrameAccess.READ_WRITE, false).materialize();
} else {
frameCount.set(frameCount.get() + 1);
return null;
}
}

});

return new RubyBinding(
getContext().getCoreLibrary().getBindingClass(),
RubyArguments.getSelf(frame.getArguments()),
frame);
}

}

}
Original file line number Diff line number Diff line change
@@ -62,12 +62,6 @@ protected Object singletonClass(double value) {
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantDefineSingleton(this));
}

@Specialization
protected Object singletonClass(RubyBignum value) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().typeErrorCantDefineSingleton(this));
}

@Specialization
protected RubyClass singletonClass(RubyBasicObject object) {
return object.getSingletonClass(this);
Original file line number Diff line number Diff line change
@@ -264,6 +264,7 @@ public void initialize() {
trueClass = new RubyClass(context, objectClass, objectClass, "TrueClass");
truffleModule = new RubyModule(context, objectClass, "Truffle");
truffleDebugModule = new RubyModule(context, truffleModule, "Debug");
new RubyModule(context, truffleModule, "Primitive");
typeErrorClass = new RubyClass(context, objectClass, standardErrorClass, "TypeError");
typeErrorClass.setAllocator(new RubyException.ExceptionAllocator());
zeroDivisionErrorClass = new RubyClass(context, objectClass, standardErrorClass, "ZeroDivisionError");
Original file line number Diff line number Diff line change
@@ -25,6 +25,11 @@ public RubyBignum(RubyClass rubyClass, BigInteger value) {
this.value = value;
}

@Override
public boolean hasNoSingleton() {
return true;
}

@CompilerDirectives.TruffleBoundary
public RubyBignum negate() {
return create(value.negate());
Original file line number Diff line number Diff line change
@@ -41,11 +41,6 @@ public boolean require(String feature, RubyNode currentNode) throws IOException
try {
// Some features are handled specially

if (feature.equals("stringio")) {
context.getCoreLibrary().loadRubyCore("jruby/truffle/standard/stringio.rb");
return true;
}

if (feature.equals("zlib")) {
context.getWarnings().warn("zlib not yet implemented");
return true;
Original file line number Diff line number Diff line change
@@ -80,8 +80,8 @@ public class BodyTranslator extends Translator {
debugIgnoredCalls.add("upto");
}

public static final Set<String> FRAME_LOCAL_GLOBAL_VARIABLES = new HashSet<>(Arrays.asList("$+", "$&", "$`", "$'"));
public static final Set<String> THREAD_LOCAL_GLOBAL_VARIABLES = new HashSet<>(Arrays.asList("$_", "$~", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9"));
public static final Set<String> FRAME_LOCAL_GLOBAL_VARIABLES = new HashSet<>(Arrays.asList("$_", "$+", "$&", "$`", "$'"));
public static final Set<String> THREAD_LOCAL_GLOBAL_VARIABLES = new HashSet<>(Arrays.asList("$~", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9")); // "$_"

public BodyTranslator(RubyNode currentNode, RubyContext context, BodyTranslator parent, TranslatorEnvironment environment, Source source, boolean topLevel) {
super(currentNode, context, source);
@@ -1146,7 +1146,7 @@ public RubyNode visitGlobalAsgnNode(org.jruby.ast.GlobalAsgnNode node) {
return new WriteInstanceVariableNode(context, sourceSection, name, threadLocalVariablesObjectNode, rhs, true);
} else if (FRAME_LOCAL_GLOBAL_VARIABLES.contains(name)) {
if (environment.getNeverAssignInParentScope()) {
environment.declareVar(node.getName());
environment.declareVar(name);
}

RubyNode localVarNode = environment.findLocalVarNode(node.getName(), sourceSection);
1 change: 0 additions & 1 deletion core/src/main/ruby/jruby/truffle/standard/stringio.rb

This file was deleted.

2 changes: 1 addition & 1 deletion default.build.properties
Original file line number Diff line number Diff line change
@@ -38,4 +38,4 @@ version.ruby=2.2.0
version.ruby.major=2.2
version.ruby.minor=0
version.ruby.patchlevel=0
version.ruby.revision=48765
version.ruby.revision=49005
21 changes: 17 additions & 4 deletions lib/ruby/stdlib/erb.rb
Original file line number Diff line number Diff line change
@@ -797,8 +797,9 @@ def initialize(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout')
@safe_level = safe_level
compiler = make_compiler(trim_mode)
set_eoutvar(compiler, eoutvar)
@src, @enc = *compiler.compile(str)
@src, @encoding = *compiler.compile(str)
@filename = nil
@lineno = 0
end

##
@@ -811,10 +812,22 @@ def make_compiler(trim_mode)
# The Ruby code generated by ERB
attr_reader :src

# The encoding to eval
attr_reader :encoding

# The optional _filename_ argument passed to Kernel#eval when the ERB code
# is run
attr_accessor :filename

# The optional _lineno_ argument passed to Kernel#eval when the ERB code
# is run
attr_accessor :lineno

def location=((filename, lineno))
@filename = filename
@lineno = lineno if lineno
end

#
# Can be used to set _eoutvar_ as described in ERB::new. It's probably
# easier to just use the constructor though, since calling this method
@@ -844,10 +857,10 @@ def result(b=new_toplevel)
if @safe_level
proc {
$SAFE = @safe_level
eval(@src, b, (@filename || '(erb)'), 0)
eval(@src, b, (@filename || '(erb)'), @lineno)
}.call
else
eval(@src, b, (@filename || '(erb)'), 0)
eval(@src, b, (@filename || '(erb)'), @lineno)
end
end

@@ -869,7 +882,7 @@ def new_toplevel
# print MyClass.new.render('foo', 123)
def def_method(mod, methodname, fname='(ERB)')
src = self.src
magic_comment = "#coding:#{@enc}\n"
magic_comment = "#coding:#{@encoding}\n"
mod.module_eval do
eval(magic_comment + "def #{methodname}\n" + src + "\nend\n", binding, fname, -2)
end
2 changes: 1 addition & 1 deletion lib/ruby/stdlib/net/http/response.rb
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ def read_new(sock) #:nodoc: internal use only

def read_status_line(sock)
str = sock.readline
m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)\s*(.*)\z/in.match(str) or
m = /\AHTTP(?:\/(\d+\.\d+))?\s+(\d\d\d)(?:\s+(.*))?\z/in.match(str) or
raise Net::HTTPBadResponse, "wrong status line: #{str.dump}"
m.captures
end
12 changes: 7 additions & 5 deletions lib/ruby/stdlib/open-uri.rb
Original file line number Diff line number Diff line change
@@ -295,10 +295,12 @@ def OpenURI.open_http(buf, target, proxy, options) # :nodoc:
http.verify_mode = options[:ssl_verify_mode] || OpenSSL::SSL::VERIFY_PEER
store = OpenSSL::X509::Store.new
if options[:ssl_ca_cert]
if File.directory? options[:ssl_ca_cert]
store.add_path options[:ssl_ca_cert]
else
store.add_file options[:ssl_ca_cert]
Array(options[:ssl_ca_cert]).each do |cert|
if File.directory? cert
store.add_path cert
else
store.add_file cert
end
end
else
store.set_default_paths
@@ -680,7 +682,7 @@ module OpenRead
#
# [:ssl_ca_cert]
# Synopsis:
# :ssl_ca_cert=>filename
# :ssl_ca_cert=>filename or an Array of filenames
#
# :ssl_ca_cert is used to specify CA certificate for SSL.
# If it is given, default certificates are not used.
30 changes: 14 additions & 16 deletions lib/ruby/stdlib/prime.rb
Original file line number Diff line number Diff line change
@@ -272,18 +272,18 @@ def rewind
end

# Iterates the given block for each prime number.
def each(&block)
return self.dup unless block
def each
return self.dup unless block_given?
if @ubound
last_value = nil
loop do
prime = succ
break last_value if prime > @ubound
last_value = block.call(prime)
last_value = yield prime
end
else
loop do
block.call(succ)
yield succ
end
end
end
@@ -350,19 +350,17 @@ def initialize
end

def succ
loop do
if (@step)
@prime += @step
@step = 6 - @step
else
case @prime
when 1; @prime = 2
when 2; @prime = 3
when 3; @prime = 5; @step = 2
end
if (@step)
@prime += @step
@step = 6 - @step
else
case @prime
when 1; @prime = 2
when 2; @prime = 3
when 3; @prime = 5; @step = 2
end
return @prime
end
return @prime
end
alias next succ
def rewind
@@ -479,7 +477,7 @@ def succ
#
# Iterates the given block over all prime numbers. Note that enumeration
# starts from the current position of internal pointer, not rewound.
def each(&block)
def each
return @generator.dup unless block_given?
loop do
yield succ
10 changes: 9 additions & 1 deletion lib/ruby/stdlib/rubygems/defaults/jruby.rb
Original file line number Diff line number Diff line change
@@ -82,7 +82,7 @@ def dirs
@@dirs ||= Gem.path.collect {|dir|
if File.file?(dir) && dir =~ /\.jar$/
"file:#{dir}!/specifications"
elsif File.directory?(dir) || dir =~ /^file:/
elsif File.directory?(File.join(dir, "specifications")) || dir =~ /^file:/
File.join(dir, "specifications")
end
}.compact + spec_directories_from_classpath
@@ -106,6 +106,14 @@ def dirs= dirs

def spec_directories_from_classpath
stuff = JRuby::Util.classloader_resources("specifications")
# some classloader return directory info. use only the "protocols"
# which jruby understands
stuff.select! { |s| File.directory?( s ) }
if File.directory?( 'uri:classloader://specifications' )
[ 'uri:classloader://specifications' ] + stuff
else
stuff
end
end
end
end
25 changes: 10 additions & 15 deletions lib/ruby/stdlib/uri/generic.rb
Original file line number Diff line number Diff line change
@@ -543,7 +543,7 @@ def set_password(v)
# if properly formatted as 'user:password'
def split_userinfo(ui)
return nil, nil unless ui
user, password = ui.split(/:/, 2)
user, password = ui.split(':'.freeze, 2)

return user, password
end
@@ -695,13 +695,7 @@ def check_port(v)
# see also URI::Generic.port=
#
def set_port(v)
unless !v || v.kind_of?(Fixnum)
if v.empty?
v = nil
else
v = v.to_i
end
end
v = v.empty? ? nil : v.to_i unless !v || v.kind_of?(Fixnum)
@port = v
end
protected :set_port
@@ -768,13 +762,14 @@ def check_path(v)

# If scheme is ftp, path may be relative.
# See RFC 1738 section 3.2.2, and RFC 2396.
if @scheme && @scheme != "ftp"
if v && v != '' && parser.regexp[:ABS_PATH] !~ v
if @scheme && @scheme != "ftp".freeze
if v && v != ''.freeze && parser.regexp[:ABS_PATH] !~ v
raise InvalidComponentError,
"bad component(expected absolute path component): #{v}"
end
else
if v && v != '' && parser.regexp[:ABS_PATH] !~ v && parser.regexp[:REL_PATH] !~ v
if v && v != ''.freeze && parser.regexp[:ABS_PATH] !~ v &&
parser.regexp[:REL_PATH] !~ v
raise InvalidComponentError,
"bad component(expected relative path component): #{v}"
end
@@ -849,9 +844,9 @@ def query=(v)
x = v.to_str
v = x.dup if x.equal? v
v.encode!(Encoding::UTF_8) rescue nil
v.delete!("\t\r\n")
v.delete!("\t\r\n".freeze)
v.force_encoding(Encoding::ASCII_8BIT)
v.gsub!(/(?!%\h\h|[!$-&(-;=?-Z_a-~])./n.freeze){'%%%02X'.freeze % $&.ord}
v.gsub!(/(?!%\h\h|[!$-&(-;=?-_a-~])./n.freeze){'%%%02X'.freeze % $&.ord}
v.force_encoding(Encoding::US_ASCII)
@query = v
end
@@ -939,9 +934,9 @@ def fragment=(v)
x = v.to_str
v = x.dup if x.equal? v
v.encode!(Encoding::UTF_8) rescue nil
v.delete!("\t\r\n")
v.delete!("\t\r\n".freeze)
v.force_encoding(Encoding::ASCII_8BIT)
v.gsub!(/(?!%\h\h|[!-~])./n){'%%%02X' % $&.ord}
v.gsub!(/(?!%\h\h|[!-~])./n){'%%%02X'.freeze % $&.ord}
v.force_encoding(Encoding::US_ASCII)
@fragment = v
end
93 changes: 54 additions & 39 deletions lib/ruby/stdlib/uri/rfc3986_parser.rb
Original file line number Diff line number Diff line change
@@ -4,49 +4,64 @@ class RFC3986_Parser # :nodoc:
# this regexp is modified not to host is not empty string
RFC3986_URI = /\A(?<URI>(?<scheme>[A-Za-z][+\-.0-9A-Za-z]*):(?<hier-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?:(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+))\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-rootless>\g<segment-nz>(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/
RFC3986_relative_ref = /\A(?<relative-ref>(?<relative-part>\/\/(?<authority>(?:(?<userinfo>(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*)@)?(?<host>(?<IP-literal>\[(?<IPv6address>(?:\h{1,4}:){6}(?<ls32>\h{1,4}:\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>))|::(?:\h{1,4}:){5}\g<ls32>|\h{1,4}?::(?:\h{1,4}:){4}\g<ls32>|(?:(?:\h{1,4}:){,1}\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>|(?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>|(?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>|(?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>|(?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}|(?:(?:\h{1,4}:){,6}\h{1,4})?::)|(?<IPvFuture>v\h+\.[!$&-.0-;=A-Z_a-z~]+)\])|\g<IPv4address>|(?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])+))?(?::(?<port>\d*))?)(?<path-abempty>(?:\/(?<segment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*))*)|(?<path-absolute>\/(?:(?<segment-nz>(?:%\h\h|[!$&-.0-;=@-Z_a-z~])+)(?:\/\g<segment>)*)?)|(?<path-noscheme>(?<segment-nz-nc>(?:%\h\h|[!$&-.0-9;=@-Z_a-z~])+)(?:\/\g<segment>)*)|(?<path-empty>))(?:\?(?<query>[^#]*))?(?:\#(?<fragment>(?:%\h\h|[!$&-.0-;=@-Z_a-z~\/?])*))?)\z/
attr_reader :regexp

def initialize
@regexp = default_regexp.each_value(&:freeze).freeze
end

def split(uri) #:nodoc:
begin
uri = uri.to_str
rescue NoMethodError
raise InvalidURIError, "bad URI(is not URI?): #{uri}"
end
unless uri.ascii_only?
uri.ascii_only? or
raise InvalidURIError, "URI must be ascii only #{uri.dump}"
end
if m = RFC3986_URI.match(uri)
ary = []
ary << m["scheme"]
if m["path-rootless"] # opaque
ary << nil # userinfo
ary << nil # host
ary << nil # port
ary << nil # registry
ary << nil # path
ary << m["path-rootless"]
ary[-1] << '?' << m["query"] if m["query"]
ary << nil # query
ary << m["fragment"]
query = m["query".freeze]
scheme = m["scheme".freeze]
opaque = m["path-rootless".freeze]
if opaque
opaque << "?#{query}" if query
[ scheme,
nil, # userinfo
nil, # host
nil, # port
nil, # registry
nil, # path
opaque,
nil, # query
m["fragment".freeze]
]
else # normal
ary << m["userinfo"]
ary << m["host"]
ary << m["port"]
ary << nil # registry
ary << (m["path-abempty"] || m["path-absolute"] || m["path-empty"])
ary << nil # opaque
ary << m["query"]
ary << m["fragment"]
[ scheme,
m["userinfo".freeze],
m["host".freeze],
m["port".freeze],
nil, # registry
(m["path-abempty".freeze] ||
m["path-absolute".freeze] ||
m["path-empty".freeze]),
nil, # opaque
query,
m["fragment".freeze]
]
end
elsif m = RFC3986_relative_ref.match(uri)
ary = [nil]
ary << m["userinfo"]
ary << m["host"]
ary << m["port"]
ary << nil # registry
ary << (m["path-abempty"] || m["path-absolute"] || m["path-noscheme"] || m["path-empty"])
ary << nil # opaque
ary << m["query"]
ary << m["fragment"]
[ nil, # scheme
m["userinfo".freeze],
m["host".freeze],
m["port".freeze],
nil, # registry,
(m["path-abempty".freeze] ||
m["path-absolute".freeze] ||
m["path-noscheme".freeze] ||
m["path-empty".freeze]),
nil, # opaque
m["query".freeze],
m["fragment".freeze]
]
else
raise InvalidURIError, "bad URI(is not URI?): #{uri}"
end
@@ -55,11 +70,11 @@ def split(uri) #:nodoc:
def parse(uri) # :nodoc:
scheme, userinfo, host, port,
registry, path, opaque, query, fragment = self.split(uri)

if scheme && URI.scheme_list.include?(scheme.upcase)
URI.scheme_list[scheme.upcase].new(scheme, userinfo, host, port,
registry, path, opaque, query,
fragment, self)
scheme_list = URI.scheme_list
if scheme && scheme_list.include?(uc = scheme.upcase)
scheme_list[uc].new(scheme, userinfo, host, port,
registry, path, opaque, query,
fragment, self)
else
Generic.new(scheme, userinfo, host, port,
registry, path, opaque, query,
@@ -78,7 +93,9 @@ def inspect
@@to_s.bind(self).call
end

def regexp
private

def default_regexp # :nodoc:
{
SCHEME: /\A[A-Za-z][A-Za-z0-9+\-.]*\z/,
USERINFO: /\A(?:%\h\h|[!$&-.0-;=A-Z_a-z~])*\z/,
@@ -92,8 +109,6 @@ def regexp
}
end

private

def convert_to_uri(uri)
if uri.is_a?(URI::Generic)
uri
20 changes: 14 additions & 6 deletions lib/ruby/stdlib/win32/registry.rb
Original file line number Diff line number Diff line change
@@ -170,12 +170,20 @@ class Error < ::StandardError
FormatMessageA = Win32API.new('kernel32.dll', 'FormatMessageA', 'LPLLPLP', 'L')
def initialize(code)
@code = code
msg = WCHAR_NUL * 1024
len = FormatMessageW.call(0x1200, 0, code, 0, msg, 1024, 0)
msg = msg.byteslice(0, len * WCHAR_SIZE)
msg.delete!(WCHAR_CR)
msg.chomp!
super msg.encode(LOCALE)
buff = WCHAR_NUL * 1024
lang = 0
begin
len = FormatMessageW.call(0x1200, 0, code, lang, buff, 1024, 0)
msg = buff.byteslice(0, len * WCHAR_SIZE)
msg.delete!(WCHAR_CR)
msg.chomp!
msg.encode!(LOCALE)
rescue EncodingError
raise unless lang == 0
lang = 0x0409 # en_US
retry
end
super msg
end
attr_reader :code
end
24 changes: 24 additions & 0 deletions lib/ruby/truffle/shims/stringio.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. This
# code is released under a tri EPL/GPL/LGPL license. You can use it,
# redistribute it and/or modify it under the terms of the:
#
# Eclipse Public License version 1.0
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

# This is shimmed specifically for RubySpec's predefined specs

class StringIO

def initialize(string, mode)
@lines = string.split(/\n/).reject { |line| line.empty? }
end

def gets
line = @lines.shift
line += "\n" unless line.nil?
Truffle::Primitive.binding_of_caller.local_variable_set(:$_, line)
line
end

end
Original file line number Diff line number Diff line change
@@ -93,7 +93,7 @@ public void testJRubyCreate() throws Exception {

String gemPath = (String) jruby.runScriptlet( "Gem::Specification.dirs.inspect" );
gemPath = gemPath.replaceAll( "bundle[^:]*://[^/]*", "bundle:/" );
assertEquals( gemPath, "[\"uri:bundle://specifications\", \"uri:classloader:/specifications\", \"uri:classloader:/META-INF/jruby.home/lib/ruby/gems/shared/specifications\"]" );
assertEquals( gemPath, "[\"uri:bundle://specifications\", \"uri:classloader:/META-INF/jruby.home/lib/ruby/gems/shared/specifications\"]" );

// ensure we can load rake from the default gems
boolean loaded = (Boolean) jruby.runScriptlet( "require 'rake'" );
Original file line number Diff line number Diff line change
@@ -93,7 +93,7 @@ public void testJRubyCreate() throws InterruptedException {

String gemPath = (String) jruby.runScriptlet( "Gem::Specification.dirs.inspect" );
gemPath = gemPath.replaceAll( "bundle[^:]*://[^/]*", "bundle:/" );
assertEquals( gemPath, "[\"uri:classloader:/specifications\", \"uri:classloader:/META-INF/jruby.home/lib/ruby/gems/shared/specifications\"]" );
assertEquals( gemPath, "[\"uri:classloader:/META-INF/jruby.home/lib/ruby/gems/shared/specifications\", \"uri:classloader://specifications\"]" );

jruby.runScriptlet( "require 'jar-dependencies'" );
list = (String) jruby.runScriptlet( "Gem.loaded_specs.keys.inspect" );
11 changes: 9 additions & 2 deletions spec/truffle/tags/language/block_tags.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
fails:Block-local variables override shadowed variables from the outer scope
fails(inherited):A block yielded a single Array assigns elements to optional arguments
fails(inherited):A block yielded a single Array calls #to_hash on the last element if keyword arguments are present
fails(inherited):A block yielded a single Array assigns the last element to a non-keyword argument if #to_hash returns nil
fails(inherited):A block yielded a single Array calls #to_hash on the element that maps to the keyword arguments
fails(inherited):A block yielded a single Array raises a TypeError if #to_hash does not return a Hash
fails(inherited):A block yielded a single Array raises the error raised inside #to_hash
fails(inherited):A block yielded a single Object receives the object if #to_ary returns nil
fails:A block yielded a single Array assigns nil to unassigned required arguments
fails:A block yielded a single Array assigns elements to optional arguments
fails:A block yielded a single Array assgins elements to post arguments
fails:A block yielded a single Array assigns elements to required arguments when a keyword rest argument is present
fails:A block yielded a single Array assigns elements to mixed argument types
fails:A block yielded a single Array calls #to_hash on the last element if keyword arguments are present
fails:A block yielded a single Array assigns the last element to a non-keyword argument if #to_hash returns nil
fails:A block yielded a single Array calls #to_hash on the element that maps to the keyword arguments
fails:A block yielded a single Array raises a TypeError if #to_hash does not return a Hash
fails:A block yielded a single Array raises the error raised inside #to_hash
fails:A block yielded a single Object receives the object if #to_ary returns nil
fails:A block yielded a single Array assigns elements to required arguments when a keyword rest argument is present
fails:Block-local variables override shadowed variables from the outer scope
12 changes: 12 additions & 0 deletions spec/truffle/tags/language/lambda_tags.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
fails(inherited):"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> (a:) { a }"
fails(inherited):"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> (*, **k) { k }"
fails(inherited):"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> (a:, b:) { [a, b] }"
fails(inherited):"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> (a:, b: 1) { [a, b] }"
fails(inherited):"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> (a: 1, b:) { [a, b] }"
fails(inherited):"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> (a: @a = -> (a: 1) { a }, b:) do\n [a, b]\n end"
fails(inherited):"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda { |a:| a }"
fails(inherited):"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda { |*, **k| k }"
fails(inherited):"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda { |a:, b:| [a, b] }"
fails(inherited):"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda { |a:, b: 1| [a, b] }"
fails(inherited):"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda { |a: 1, b:| [a, b] }"
fails(inherited):"A lambda expression 'lambda { ... }' assigns variables from parameters for definition \n @a = lambda do |a: (@a = -> (a: 1) { a }), b:|\n [a, b]\n end"
fails:"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> ((*a, b)) { [a, b] }"
fails:"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> (a:) { a }"
fails:"A lambda literal -> () { } assigns variables from parameters for definition \n @a = -> ((a, b, *c, d), (*e, f, g), (*h)) do\n [a, b, c, d, e, f, g, h]\n end"
3 changes: 3 additions & 0 deletions spec/truffle/tags/language/method_tags.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
fails(inherited):"A method assigns local variables from method parameters for definition \n def m(*, **) end"
fails(inherited):"A method assigns local variables from method parameters for definition \n def m(*a, **) a end"
fails(inherited):"A method assigns local variables from method parameters for definition \n def m(*, **k) k end"
fails:"A method assigns local variables from method parameters for definition \n def m((*a, b)) [a, b] end"
fails:"A method assigns local variables from method parameters for definition \n def m((*a), (*b)) [a, b] end"
fails:"A method assigns local variables from method parameters for definition \n def m((a, *b), (*c, d))\n [a, b, c, d]\n end"
3 changes: 1 addition & 2 deletions spec/truffle/tags/language/predefined_tags.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
fails:Predefined global $! remains nil after a failed core class "checked" coercion against a class that defines method_missing
fails(uses StringIO):Predefined global $_ is set at the method-scoped level rather than block-scoped
fails(uses StringIO):Predefined global $_ is set to the last line read by e.g. StringIO#gets
fails:Predefined global $_ is Thread-local
11 changes: 11 additions & 0 deletions spec/truffle/tags/language/variables_tags.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
fails(inherited):Basic multiple assignment with a splatted single RHS value does not call #to_ary on an object
fails(inherited):Basic multiple assignment with a splatted single RHS value calls #to_a even if it's private
fails(inherited):Multiple assignment with a single RHS value does not call #to_ary if #respond_to? returns false
fails(inherited):Multiple assignment with a single RHS value raises a TypeError of #to_ary does not return an Array
fails(inherited):Multiple assignment with a single RHS value raises a TypeError if #to_ary does not return an Array
fails(inherited):Multiple assignment with a single RHS value assigns an Array when the RHS is an Array subclass
fails(inherited):Multiple assignment with a single splatted RHS value calls #to_a to convert nil to an empty Array
fails(inherited):Multiple assignment with a single splatted RHS value does not call #to_a if #respond_to? returns false
fails(inherited):Multiple assignment with a MRHS value raises a TypeError if #to_ary does not return an Array
fails(inherited):Multiple assignment with a MRHS value calls #to_ary to convert a splatted Object when the position receiving the value is a multiple assignment
fails(inherited):Multiple assignment with a MRHS value does not call #to_ary to convert a splatted Object when the position receiving the value is a simple variable
fails:Multiple assignment with a single RHS value calls #to_ary to convert an Object RHS when assigning a simple MLHS
fails:Multiple assignment with a single RHS value calls #to_ary if it is private
fails:Multiple assignment with a single RHS value does not call #to_ary if #respond_to? returns false

0 comments on commit ee07e39

Please sign in to comment.