Skip to content
Merged
Show file tree
Hide file tree
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
9 changes: 8 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ Note: We're only listing outstanding class updates.
* `Array#pack` accepts a new format `R` and `r` for unpacking unsigned
and signed LEB128 encoded integers. [[Feature #21785]]

* Regexp

* All instances of `Regexp` are now frozen, not just literals.
Subclasses of `Regexp` are not frozen for compatibility.
[[Feature #8948]]

* Set

* A deprecated behavior, `Set#to_set`, `Range#to_set`, and
Expand Down Expand Up @@ -69,7 +75,7 @@ releases.

* RubyGems 4.1.0.dev
* bundler 4.1.0.dev
* json 2.19.2
* json 2.19.3
* 2.18.0 to [v2.18.1][json-v2.18.1], [v2.19.0][json-v2.19.0], [v2.19.1][json-v2.19.1], [v2.19.2][json-v2.19.2]
* openssl 4.0.1
* 4.0.0 to [v4.0.1][openssl-v4.0.1]
Expand Down Expand Up @@ -140,6 +146,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable.
## JIT

[Feature #6012]: https://bugs.ruby-lang.org/issues/6012
[Feature #8948]: https://bugs.ruby-lang.org/issues/8948
[Feature #15330]: https://bugs.ruby-lang.org/issues/15330
[Feature #21390]: https://bugs.ruby-lang.org/issues/21390
[Feature #21785]: https://bugs.ruby-lang.org/issues/21785
Expand Down
1 change: 1 addition & 0 deletions depend
Original file line number Diff line number Diff line change
Expand Up @@ -8862,6 +8862,7 @@ marshal.$(OBJEXT): $(top_srcdir)/internal/hash.h
marshal.$(OBJEXT): $(top_srcdir)/internal/imemo.h
marshal.$(OBJEXT): $(top_srcdir)/internal/numeric.h
marshal.$(OBJEXT): $(top_srcdir)/internal/object.h
marshal.$(OBJEXT): $(top_srcdir)/internal/re.h
marshal.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
marshal.$(OBJEXT): $(top_srcdir)/internal/serial.h
marshal.$(OBJEXT): $(top_srcdir)/internal/set_table.h
Expand Down
2 changes: 1 addition & 1 deletion ext/json/lib/json/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module JSON
VERSION = '2.19.2'
VERSION = '2.19.3'
end
4 changes: 3 additions & 1 deletion ext/json/parser/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,9 @@ NOINLINE(static) VALUE json_string_unescape(JSON_ParserState *state, JSON_Parser
}
raise_parse_error_at("invalid ASCII control character in string: %s", state, pe - 1);
}
} else if (config->allow_invalid_escape) {
}

if (config->allow_invalid_escape) {
APPEND_CHAR(*pe);
} else {
raise_parse_error_at("invalid escape character in string: %s", state, pe - 1);
Expand Down
5 changes: 0 additions & 5 deletions gc/default/default.c
Original file line number Diff line number Diff line change
Expand Up @@ -9532,11 +9532,6 @@ rb_gc_impl_objspace_init(void *objspace_ptr)
rb_darray_make_without_gc(&objspace->heap_pages.sorted, 0);
rb_darray_make_without_gc(&objspace->weak_references, 0);

// TODO: debug why on Windows Ruby crashes on boot when GC is on.
#ifdef _WIN32
dont_gc_on();
#endif

#if defined(INIT_HEAP_PAGE_ALLOC_USE_MMAP)
/* Need to determine if we can use mmap at runtime. */
heap_page_alloc_use_mmap = INIT_HEAP_PAGE_ALLOC_USE_MMAP;
Expand Down
2 changes: 1 addition & 1 deletion gems/bundled_gems
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ net-imap 0.6.3 https://github.com/ruby/net-imap
net-smtp 0.5.1 https://github.com/ruby/net-smtp
matrix 0.4.3 https://github.com/ruby/matrix
prime 0.1.4 https://github.com/ruby/prime
rbs 3.10.3 https://github.com/ruby/rbs
rbs 4.0.2 https://github.com/ruby/rbs
typeprof 0.31.1 https://github.com/ruby/typeprof
debug 1.11.1 https://github.com/ruby/debug
racc 1.8.1 https://github.com/ruby/racc
Expand Down
2 changes: 1 addition & 1 deletion include/ruby/internal/core/rmatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ struct rmatch_offset {
struct rb_matchext_struct {
/**
* "Registers" of a match. This is a quasi-opaque struct that holds
* execution result of a match. Roughly resembles `&~`.
* execution result of a match. Roughly resembles `$~`.
*/
struct re_registers regs;

Expand Down
1 change: 1 addition & 0 deletions internal/re.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "ruby/ruby.h" /* for VALUE */

/* re.c */
VALUE rb_reg_s_alloc(VALUE klass);
VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline);
VALUE rb_reg_check_preprocess(VALUE);
long rb_reg_search0(VALUE, VALUE, long, int, int, VALUE *);
Expand Down
32 changes: 29 additions & 3 deletions lib/bundler/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -265,14 +265,40 @@ def message
class InvalidArgumentError < BundlerError; status_code(40); end

class IncorrectLockfileDependencies < BundlerError
attr_reader :spec
attr_reader :spec, :actual_dependencies, :lockfile_dependencies

def initialize(spec)
def initialize(spec, actual_dependencies = nil, lockfile_dependencies = nil)
@spec = spec
@actual_dependencies = actual_dependencies
@lockfile_dependencies = lockfile_dependencies
end

def message
"Bundler found incorrect dependencies in the lockfile for #{spec.full_name}"
lines = ["Bundler found incorrect dependencies in the lockfile for #{spec.full_name}", ""]

if @actual_dependencies && @lockfile_dependencies
actual_by_name = @actual_dependencies.each_with_object({}) {|d, h| h[d.name] = d }
lockfile_by_name = @lockfile_dependencies.each_with_object({}) {|d, h| h[d.name] = d }

(actual_by_name.keys | lockfile_by_name.keys).sort.each do |name|
actual = actual_by_name[name]
lockfile = lockfile_by_name[name]
next if actual && lockfile && actual.requirement == lockfile.requirement

if actual && lockfile
lines << " #{name}: gemspec specifies #{actual.requirement}, lockfile has #{lockfile.requirement}"
elsif actual
lines << " #{name}: gemspec specifies #{actual.requirement}, not in lockfile"
else
lines << " #{name}: not in gemspec, lockfile has #{lockfile.requirement}"
end
end

lines << ""
end

lines << "Please run `bundle install` to regenerate the lockfile."
lines.join("\n")
end

status_code(41)
Expand Down
2 changes: 1 addition & 1 deletion lib/bundler/lazy_specification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ def validate_dependencies(spec)
spec.dependencies = dependencies
else
if !source.is_a?(Source::Path) && spec.runtime_dependencies.sort != dependencies.sort
raise IncorrectLockfileDependencies.new(self)
raise IncorrectLockfileDependencies.new(self, spec.runtime_dependencies, dependencies)
end
end
end
Expand Down
46 changes: 42 additions & 4 deletions lib/bundler/plugin/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ def installed_in_plugin_root?(name)
# @param [Pathname] index file path
# @param [Boolean] is the index file global index
def load_index(index_file, global = false)
base = base_for_index(global)

SharedHelpers.filesystem_access(index_file, :read) do |index_f|
valid_file = index_f&.exist? && !index_f.size.zero?
break unless valid_file
Expand All @@ -174,8 +176,8 @@ def load_index(index_file, global = false)

@commands.merge!(index["commands"])
@hooks.merge!(index["hooks"])
@load_paths.merge!(index["load_paths"])
@plugin_paths.merge!(index["plugin_paths"])
@load_paths.merge!(transform_index_paths(index["load_paths"]) {|p| absolutize_path(p, base) })
@plugin_paths.merge!(transform_index_paths(index["plugin_paths"]) {|p| absolutize_path(p, base) })
@sources.merge!(index["sources"]) unless global
end
end
Expand All @@ -184,11 +186,13 @@ def load_index(index_file, global = false)
# instance variables in YAML format. (The instance variables are supposed
# to be only String key value pairs)
def save_index
base = base_for_index(false)

index = {
"commands" => @commands,
"hooks" => @hooks,
"load_paths" => @load_paths,
"plugin_paths" => @plugin_paths,
"load_paths" => transform_index_paths(@load_paths) {|p| relativize_path(p, base) },
"plugin_paths" => transform_index_paths(@plugin_paths) {|p| relativize_path(p, base) },
"sources" => @sources,
}

Expand All @@ -198,6 +202,40 @@ def save_index
File.open(index_f, "w") {|f| f.puts YAMLSerializer.dump(index) }
end
end

def base_for_index(global)
global ? Plugin.global_root : Plugin.root
end

def transform_index_paths(paths)
return {} unless paths

paths.transform_values do |value|
if value.is_a?(Array)
value.map {|path| yield path }
else
yield value
end
end
end

def relativize_path(path, base)
pathname = Pathname.new(path)
return path unless pathname.absolute?

base_path = Pathname.new(base)
if pathname == base_path || pathname.to_s.start_with?(base_path.to_s + File::SEPARATOR)
pathname.relative_path_from(base_path).to_s
else
path
end
end

def absolutize_path(path, base)
pathname = Pathname.new(path)
pathname = Pathname.new(base).join(pathname) unless pathname.absolute?
pathname.to_s
end
end
end
end
21 changes: 14 additions & 7 deletions marshal.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "internal/hash.h"
#include "internal/numeric.h"
#include "internal/object.h"
#include "internal/re.h"
#include "internal/struct.h"
#include "internal/symbol.h"
#include "internal/util.h"
Expand Down Expand Up @@ -1731,7 +1732,10 @@ r_ivar_encoding(VALUE obj, struct load_arg *arg, VALUE sym, VALUE val)
int idx = sym2encidx(sym, val);
if (idx >= 0) {
if (rb_enc_capable(obj)) {
rb_enc_associate_index(obj, idx);
// Check if needed to avoid rb_check_frozen() check for Regexps
if (rb_enc_get_index(obj) != idx) {
rb_enc_associate_index(obj, idx);
}
}
else {
rb_raise(rb_eArgError, "%"PRIsVALUE" is not enc_capable", obj);
Expand Down Expand Up @@ -1854,17 +1858,17 @@ append_extmod(VALUE obj, VALUE extmod)
override_ivar_error(type, str); \
} while (0)

static VALUE r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type);
static VALUE r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE klass, VALUE extmod, int type);

static VALUE
r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod)
{
int type = r_byte(arg);
return r_object_for(arg, partial, ivp, extmod, type);
return r_object_for(arg, partial, ivp, 0, extmod, type);
}

static VALUE
r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type)
r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE klass, VALUE extmod, int type)
{
VALUE (*hash_new_with_size)(st_index_t) = rb_hash_new_with_size;
VALUE v = Qnil;
Expand Down Expand Up @@ -1940,12 +1944,12 @@ r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int typ
}
type = r_byte(arg);
if ((c == rb_cHash) &&
/* Hack for compare_by_identify */
/* Hack for compare_by_identity */
(type == TYPE_HASH || type == TYPE_HASH_DEF)) {
hash_new_with_size = rb_ident_hash_new_with_size;
goto type_hash;
}
v = r_object_for(arg, partial, 0, extmod, type);
v = r_object_for(arg, partial, 0, c, extmod, type);
if (RB_SPECIAL_CONST_P(v) || RB_TYPE_P(v, T_OBJECT) || RB_TYPE_P(v, T_CLASS)) {
goto format_error;
}
Expand Down Expand Up @@ -2082,7 +2086,10 @@ r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int typ
}
rb_str_set_len(str, dst - ptr);
}
VALUE regexp = rb_reg_new_str(str, options);
if (!klass) {
klass = rb_cRegexp;
}
VALUE regexp = rb_reg_init_str(rb_reg_s_alloc(klass), str, options);
r_copy_ivar(regexp, str);

v = r_entry0(regexp, idx, arg);
Expand Down
16 changes: 11 additions & 5 deletions re.c
Original file line number Diff line number Diff line change
Expand Up @@ -3368,6 +3368,9 @@ rb_reg_initialize(VALUE obj, const char *s, long len, rb_encoding *enc,
options & ARG_REG_OPTION_MASK, err,
sourcefile, sourceline);
if (!re->ptr) return -1;
if (RBASIC_CLASS(obj) == rb_cRegexp) {
OBJ_FREEZE(obj);
}
RB_GC_GUARD(unescaped);
return 0;
}
Expand Down Expand Up @@ -3407,7 +3410,7 @@ rb_reg_initialize_str(VALUE obj, VALUE str, int options, onig_errmsg_buffer err,
return ret;
}

static VALUE
VALUE
rb_reg_s_alloc(VALUE klass)
{
NEWOBJ_OF(re, struct RRegexp, klass, T_REGEXP | (RGENGC_WB_PROTECTED_REGEXP ? FL_WB_PROTECTED : 0), sizeof(struct RRegexp), 0);
Expand Down Expand Up @@ -3460,9 +3463,7 @@ rb_reg_init_str_enc(VALUE re, VALUE s, rb_encoding *enc, int options)
VALUE
rb_reg_new_ary(VALUE ary, int opt)
{
VALUE re = rb_reg_new_str(rb_reg_preprocess_dregexp(ary, opt), opt);
rb_obj_freeze(re);
return re;
return rb_reg_new_str(rb_reg_preprocess_dregexp(ary, opt), opt);
}

VALUE
Expand Down Expand Up @@ -3496,7 +3497,6 @@ rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline)
rb_set_errinfo(rb_reg_error_desc(str, options, err));
return Qnil;
}
rb_obj_freeze(re);
return re;
}

Expand Down Expand Up @@ -4033,6 +4033,9 @@ reg_copy(VALUE copy, VALUE orig)
RREGEXP_PTR(copy)->timelimit = RREGEXP_PTR(orig)->timelimit;
rb_enc_copy(copy, orig);
FL_SET_RAW(copy, FL_TEST_RAW(orig, KCODE_FIXED|REG_ENCODING_NONE));
if (RBASIC_CLASS(copy) == rb_cRegexp) {
OBJ_FREEZE(copy);
}

return copy;
}
Expand Down Expand Up @@ -4115,6 +4118,9 @@ rb_reg_initialize_m(int argc, VALUE *argv, VALUE self)
}

set_timeout(&RREGEXP_PTR(self)->timelimit, args.timeout);
if (RBASIC_CLASS(self) == rb_cRegexp) {
OBJ_FREEZE(self);
}

return self;
}
Expand Down
Loading