From a48d512be20096fd44ef9c984ea90597035a58a4 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 12 Nov 2021 16:04:15 +0100 Subject: [PATCH 1/6] Process source mapping URLs be set by transpilers Rewrites source mapping urls with the digested paths and protect against semicolon appending with a dummy comment line. --- .../rails/sourcemapping_url_processor.rb | 19 +++++++++++++++++++ lib/sprockets/railtie.rb | 5 +++++ 2 files changed, 24 insertions(+) create mode 100644 lib/sprockets/rails/sourcemapping_url_processor.rb diff --git a/lib/sprockets/rails/sourcemapping_url_processor.rb b/lib/sprockets/rails/sourcemapping_url_processor.rb new file mode 100644 index 00000000..6ff18a50 --- /dev/null +++ b/lib/sprockets/rails/sourcemapping_url_processor.rb @@ -0,0 +1,19 @@ +module Sprockets + module Rails + # Rewrites source mapping urls with the digested paths and protect against semicolon appending with a dummy comment line + class SourcemappingUrlProcessor + REGEX = /\/\/# sourceMappingURL=(.*\.map)/ + + def self.call(input) + context = input[:environment].context_class.new(input) + data = input[:data].gsub(REGEX) do |_match| + "//# sourceMappingURL=#{context.asset_path($1)}\n//!\n" + end + rescue Sprockets::FileNotFound + # Remove source mapping when the target cannot be found + + { data: data } + end + end + end +end diff --git a/lib/sprockets/railtie.rb b/lib/sprockets/railtie.rb index d7434523..997650dd 100644 --- a/lib/sprockets/railtie.rb +++ b/lib/sprockets/railtie.rb @@ -6,6 +6,7 @@ require 'sprockets' require 'sprockets/rails/asset_url_processor' +require 'sprockets/rails/sourcemap_url_processor' require 'sprockets/rails/context' require 'sprockets/rails/helper' require 'sprockets/rails/quiet_assets' @@ -122,6 +123,10 @@ def configure(&block) Sprockets.register_postprocessor "text/css", ::Sprockets::Rails::AssetUrlProcessor end + initializer :asset_sourcemap_url_processor do |app| + Sprockets.register_postprocessor "application/javascript", ::Sprockets::Rails::SourcemappingUrlProcessor + end + config.assets.version = "" config.assets.debug = false config.assets.compile = true From 6e589daeb6c263c03fcbe36247cdc3db11e7f639 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 12 Nov 2021 16:06:13 +0100 Subject: [PATCH 2/6] Correct file name --- lib/sprockets/railtie.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/sprockets/railtie.rb b/lib/sprockets/railtie.rb index 997650dd..5651faf7 100644 --- a/lib/sprockets/railtie.rb +++ b/lib/sprockets/railtie.rb @@ -6,7 +6,7 @@ require 'sprockets' require 'sprockets/rails/asset_url_processor' -require 'sprockets/rails/sourcemap_url_processor' +require 'sprockets/rails/sourcemapping_url_processor' require 'sprockets/rails/context' require 'sprockets/rails/helper' require 'sprockets/rails/quiet_assets' From a5b7cb2c344eba130068c98c5c9749dcb1a00203 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 12 Nov 2021 16:23:35 +0100 Subject: [PATCH 3/6] Correct indention --- lib/sprockets/rails/sourcemapping_url_processor.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/sprockets/rails/sourcemapping_url_processor.rb b/lib/sprockets/rails/sourcemapping_url_processor.rb index 6ff18a50..f89a8f28 100644 --- a/lib/sprockets/rails/sourcemapping_url_processor.rb +++ b/lib/sprockets/rails/sourcemapping_url_processor.rb @@ -8,9 +8,9 @@ def self.call(input) context = input[:environment].context_class.new(input) data = input[:data].gsub(REGEX) do |_match| "//# sourceMappingURL=#{context.asset_path($1)}\n//!\n" + rescue Sprockets::FileNotFound + # Remove source mapping when the target cannot be found end - rescue Sprockets::FileNotFound - # Remove source mapping when the target cannot be found { data: data } end From a19271c4180e697b45f99eb49da26f685e37f25c Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 12 Nov 2021 17:34:52 +0100 Subject: [PATCH 4/6] Ensure files that can't resolve raise --- lib/sprockets/rails/sourcemapping_url_processor.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/sprockets/rails/sourcemapping_url_processor.rb b/lib/sprockets/rails/sourcemapping_url_processor.rb index f89a8f28..877ffe16 100644 --- a/lib/sprockets/rails/sourcemapping_url_processor.rb +++ b/lib/sprockets/rails/sourcemapping_url_processor.rb @@ -7,6 +7,7 @@ class SourcemappingUrlProcessor def self.call(input) context = input[:environment].context_class.new(input) data = input[:data].gsub(REGEX) do |_match| + ensure_file_is_present = context.resolve($1) "//# sourceMappingURL=#{context.asset_path($1)}\n//!\n" rescue Sprockets::FileNotFound # Remove source mapping when the target cannot be found From 87575ccb2bfe570938a9c821bb4820f947ddd1f6 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Fri, 12 Nov 2021 17:35:00 +0100 Subject: [PATCH 5/6] Test source mapping url processor --- test/test_sourcemapping_url_processor.rb | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 test/test_sourcemapping_url_processor.rb diff --git a/test/test_sourcemapping_url_processor.rb b/test/test_sourcemapping_url_processor.rb new file mode 100644 index 00000000..a35d04b2 --- /dev/null +++ b/test/test_sourcemapping_url_processor.rb @@ -0,0 +1,38 @@ +require 'minitest/autorun' +require 'sprockets/railtie' + + +Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test) +class TestSourceMappingUrlProcessor < Minitest::Test + def setup + @env = Sprockets::Environment.new + end + + def test_successful + @env.context_class.class_eval do + def resolve(path, **kargs) + "/yes" + end + + def asset_path(path, options = {}) + 'mapped-HEXGOESHERE.js.map' + end + end + + input = { environment: @env, data: "var mapped;\n//# sourceMappingURL=mapped.js.map", filename: 'mapped.js', metadata: {} } + output = Sprockets::Rails::SourcemappingUrlProcessor.call(input) + assert_equal({ data: "var mapped;\n//# sourceMappingURL=mapped-HEXGOESHERE.js.map\n//!\n" }, output) + end + + def test_missing + @env.context_class.class_eval do + def resolve(path, **kargs) + raise Sprockets::FileNotFound + end + end + + input = { environment: @env, data: "var mapped;\n//# sourceMappingURL=mappedNOT.js.map", filename: 'mapped.js', metadata: {} } + output = Sprockets::Rails::SourcemappingUrlProcessor.call(input) + assert_equal({ data: "var mapped;\n" }, output) + end +end From 4571493dad9db368bfa70664d7c1cad33a138302 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 15 Nov 2021 15:55:53 +0100 Subject: [PATCH 6/6] Warn in the log about removing the sourceMappingURL on missing assets --- lib/sprockets/rails/sourcemapping_url_processor.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/sprockets/rails/sourcemapping_url_processor.rb b/lib/sprockets/rails/sourcemapping_url_processor.rb index 877ffe16..599deeb4 100644 --- a/lib/sprockets/rails/sourcemapping_url_processor.rb +++ b/lib/sprockets/rails/sourcemapping_url_processor.rb @@ -5,12 +5,14 @@ class SourcemappingUrlProcessor REGEX = /\/\/# sourceMappingURL=(.*\.map)/ def self.call(input) - context = input[:environment].context_class.new(input) + env = input[:environment] + context = env.context_class.new(input) data = input[:data].gsub(REGEX) do |_match| ensure_file_is_present = context.resolve($1) "//# sourceMappingURL=#{context.asset_path($1)}\n//!\n" rescue Sprockets::FileNotFound - # Remove source mapping when the target cannot be found + env.logger.warn "Removed sourceMappingURL comment for missing asset '#{$1}' from #{input[:filename]}" + nil end { data: data }