New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
handle source-map
operations internally
#3754
Conversation
@@ -245,7 +245,7 @@ describe("bin/uglifyjs", function() { | |||
if (err) throw err; | |||
assert.strictEqual(stdout, [ | |||
"var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();", | |||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUFBLE1BQWdCQyxRQUFRQyxJQUFJLEVBQUUsSUFBTyxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==", | |||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUVBLE1BQWNDLFFBQVFDLElBQUksRUFBRSxJQUFPLElBQUlGLElDQW5ELElBQUlHLElBQU0sV0FDTixTQUFTQyxJQUFLRCxLQUNWLE9BQU9BLElBR1gsT0FBT0MsSUFMRCJ9", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While all the other source map tests are updated due to sourceRoot
now appearing in the order as documented, this one is due to difference in resolving non-exact position match on overlapped mappings input source map:
{"source":"stdin","generatedLine":1,"generatedColumn":10,"originalLine":1,"originalColumn":10,"name":null}
{"source":"stdin","generatedLine":1,"generatedColumn":10,"originalLine":1,"originalColumn":12,"name":null}
{"source":"stdin","generatedLine":1,"generatedColumn":22,"originalLine":1,"originalColumn":23,"name":null}
When looking up for generatedColumn=13
, source-map
used to get stuck on originalColumn:10
while this PR will report originalColumn:11
instead.
Well done! Like you, I don't use source maps. But you might try timing large bundles compared to the old version. You can also try using https://sokra.github.io/source-map-visualization/ - click on the |
Tested with |
I ran the following command against a 5MB bundle and took the average timings of five runs using:
It appears that this PR is just a touch slower than Edit: timings were corrected - the numbers were previously reversed. |
May well be my reading comprehension, but isn't (with PR) 2.380s faster than 2.438s? 😅 |
You read it before I had the chance to correct it. I had reversed the numbers. |
The difference in timings is not significant. Keep in mind that in my 5MB example the source map creation only accounts for 0.5s of the 2.4s total run time. To get more accurate timings you should test against a larger input. Looking at the diff, there's no obvious inefficiency there. I'm guessing that the map lookups take up the majority of the time. I suppose you could run it through a profiler if you care to speed it up. |
Well as long as it has acceptable performance I'd rather worry more on correctness at this stage. One thing reading the specification is that they have one-field segments − I don't understand how I've tested with various combinations of flags with |
I think this is what magic-string calls "high resolution" source maps where the mappings are not associated with names, but merely positions. This may be related: Rich-Harris/magic-string#167 |
magic-string |
Just read through it & they would only emits four/five-length segments as well. |
Hmm. Then I'm stumped. |
According to https://coffeescript.org/annotated-source/sourcemap.html
|
May be it's for cases where new code is inserted & you want to stop that fuzzy location lookup from landing on the wrong original location. |
It seems unnecessary and would bloat the source map, but that must be the reason. I wonder if any major tool creates 1 field segments. Although uglify doesn't emit such segments, could it handle input source maps using them? i.e., ignore such mappings? |
It just occurred to me that 1 field segments need not necessarily be inefficient - rather than marking every single generated character, you'd only need to mark the first generated character at the start of each generated block of characters. That would be enough information to signal to the source map consumer (typically a browser) where the previous 4/5 field source mapping ends. I always wondered why the source map mapping did not support a length - that workaround may be the reason. |
There are many things this format that is counter-intuitive & inefficient, so there's that 😉 I think now that I understand the single-field case we need to skip them during lookups. |
I suppose the 1 field |
|
While the direct output case has similar performace to
|
Good stuff. There may also be some source map computation caching opportunities when I glanced at the code. Perhaps not worth the trouble. Now you only need to get rid of |
Could you rerun the timings with |
$ uglifyjs es5.js -b braces --rename --source-map names=false -o test.js --timings
- parse: 4.317s
- rename: 3.097s
- compress: 0.000s
- scope: 0.000s
- mangle: 0.000s
- properties: 0.000s
- output: 5.671s
- total: 13.085s $ uglifyjs test.js -mc --source-map content=test.js.map,names=false -o min.js --timings
- parse: 4.250s
- rename: 3.048s
- compress: 44.155s
- scope: 1.829s
- mangle: 4.943s
- properties: 0.000s
- output: 6.152s
- total: 64.377s
|
Not bad at all. So on average In a future minor bump you might consider changing the default to |
@kzc managed to get this past the current test suite − any particular workload you have to throw at this would be welcome.