From cfdb9ccae4038c4dcf037da9d10c9dcc8e4df6c9 Mon Sep 17 00:00:00 2001 From: Oskar Eichler <62393985+OskarEichler@users.noreply.github.com> Date: Sun, 30 Aug 2026 07:25:07 +0200 Subject: [PATCH] Avoid allocating source lines when counting --- CHANGELOG.md | 2 ++ README.md | 2 ++ lib/sprockets/preprocessors/default_source_map.rb | 10 ++++++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6366a4d92..a63a86e67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ **Master** +- Count default source-map lines without allocating every source line. [Oskar Eichler](https://github.com/OskarEichler) + Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprockets/blob/master/UPGRADING.md # 4.4.1 diff --git a/README.md b/README.md index 958b44cd4..8e97f6c44 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ If you want to work on Sprockets or better understand how it works read [How Spr ## Behavior Overview +Default source-map line counting avoids retaining an array of every source line. + You can interact with Sprockets primarily through directives and file extensions. This section covers how to use each of these things, and the defaults that ship with Sprockets. Since you are likely using Sprockets through another framework (such as the [Rails asset pipeline](http://guides.rubyonrails.org/asset_pipeline.html)), there will be configuration options you can toggle that will change behavior such as what directories or files get compiled. For that documentation you should see your framework's documentation. diff --git a/lib/sprockets/preprocessors/default_source_map.rb b/lib/sprockets/preprocessors/default_source_map.rb index 7f8c9340e..f5584f510 100644 --- a/lib/sprockets/preprocessors/default_source_map.rb +++ b/lib/sprockets/preprocessors/default_source_map.rb @@ -9,11 +9,17 @@ module Preprocessors # available. class DefaultSourceMap def call(input) - result = { data: input[:data] } + data = input[:data] + result = { data: data } map = input[:metadata][:map] filename = input[:filename] load_path = input[:load_path] - lines = input[:data].lines.length + if data.encoding.ascii_compatible? + lines = data.b.count("\n") + lines += 1 unless data.empty? || data.end_with?("\n") + else + lines = data.each_line.count + end basename = File.basename(filename) mime_exts = input[:environment].config[:mime_exts] pipeline_exts = input[:environment].config[:pipeline_exts]