From 8b0ff49d78927d9a19e03a431b1d9c25620cf60c Mon Sep 17 00:00:00 2001 From: David Taylor Date: Tue, 18 Nov 2025 22:05:54 +0000 Subject: [PATCH] Update asset digests when sourcemaps change When sourcemaps change, their digest will change, and the generated URL in the `# sourceMappingURL` comment will change. Therefore, it's important that the digest of the original asset also changes, so that caches can be invalidated correctly. This change makes use of the existing `#referenced_by` API in the SourceMappingUrls compiler, and implements the tests in a similar way to 59406abcfa479468f1865addc7f636a6dd91c400. --- lib/propshaft/compiler/source_mapping_urls.rb | 8 ++++++ .../compiler/source_mapping_urls_test.rb | 27 +++++++++++++++++++ test/test_helper.rb | 4 +-- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/lib/propshaft/compiler/source_mapping_urls.rb b/lib/propshaft/compiler/source_mapping_urls.rb index d15e862e..3865ae16 100644 --- a/lib/propshaft/compiler/source_mapping_urls.rb +++ b/lib/propshaft/compiler/source_mapping_urls.rb @@ -9,6 +9,14 @@ def compile(asset, input) input.gsub(SOURCE_MAPPING_PATTERN) { source_mapping_url(asset.logical_path, asset_path($2, asset.logical_path), $1, $3) } end + def referenced_by(asset, references: Set.new) + asset.content.scan(SOURCE_MAPPING_PATTERN).each do |_, source_mapping_url, _| + sourcemap_asset = load_path.find(asset_path(source_mapping_url, asset.logical_path)) + references << sourcemap_asset if sourcemap_asset + end + references + end + private def asset_path(source_mapping_url, logical_path) source_mapping_url.gsub!(/^(.+\/)?#{url_prefix}\//, "") diff --git a/test/propshaft/compiler/source_mapping_urls_test.rb b/test/propshaft/compiler/source_mapping_urls_test.rb index ca06d20a..282ab7c7 100644 --- a/test/propshaft/compiler/source_mapping_urls_test.rb +++ b/test/propshaft/compiler/source_mapping_urls_test.rb @@ -72,6 +72,24 @@ class Propshaft::Compiler::SourceMappingUrlsTest < ActiveSupport::TestCase compile_asset(find_asset("source.js", fixture_path: "mapped")) end + test "changes to sourcemap are reflected in parent digest" do + root_path = Pathname.new("#{__dir__}/../../fixtures/assets/mapped") + assembly = Propshaft::Assembly.new(ActiveSupport::OrderedOptions.new.tap { |config| + config.paths = [ root_path ] + config.compilers = [[ "text/javascript", Propshaft::Compiler::SourceMappingUrls ]] + }) + + digest = find_asset("source.js", fixture_path: "mapped", load_path: assembly.load_path).digest + + open_asset_with_reset("mapped/source.js.map") do |sourcemap_file| + sourcemap_file.write "changes!" + sourcemap_file.flush + + new_digest = find_asset("source.js", fixture_path: "mapped", load_path: assembly.load_path).digest + assert_not_equal digest, new_digest + end + end + private def compile_asset(asset) @@ -81,6 +99,15 @@ def compile_asset(asset) assembly.compilers.compile(asset) end + + def open_asset_with_reset(logical_path) + dependency_path = Pathname.new("#{__dir__}/../../fixtures/assets/#{logical_path}") + existing_dependency_content = File.read(dependency_path) + + File.open(dependency_path, "a") { |f| yield f } + ensure + File.write(dependency_path, existing_dependency_content) + end end # //# sourceMappingURL=/assets/sourceMappingURL-already-prefixed.js-[a-z0-9]{40}.map diff --git a/test/test_helper.rb b/test/test_helper.rb index 082142df..ccecdcce 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -11,10 +11,10 @@ class ActiveSupport::TestCase private - def find_asset(logical_path, fixture_path:) + def find_asset(logical_path, fixture_path:, load_path: nil) root_path = Pathname.new("#{__dir__}/fixtures/assets/#{fixture_path}") path = root_path.join(logical_path) - load_path = Propshaft::LoadPath.new([ root_path ], compilers: Propshaft::Compilers.new(nil)) + load_path ||= Propshaft::LoadPath.new([ root_path ], compilers: Propshaft::Compilers.new(nil)) Propshaft::Asset.new(path, logical_path: logical_path, load_path: load_path) end