question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Insertion of globals breaks sourcemaps

See original GitHub issue

When a source file that already has a sourcemap (from a prior transform) is transformed to insert globals, the sourcemap is not updated, which breaks all positions in the file thereafter.

A trivial reproducing test case using coffeeify (this bug has nothing to do with coffeeify specifically; any transform that uses sourcemaps is affected):

x.coffee

global.foo = 3
console.log('hello')

command line

browserify -t coffeeify -d x.coffee

This link shows the resulting sourcemap. Note how the addition of the (function (global){ line causes the mappings to be off by exactly one line at that point. This offset will persist through the entire bundle, as the mappings are calculated relative to the original output rather than the transformed output.

Issue Analytics

  • State:open
  • Created 9 years ago
  • Comments:16 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
brettz9commented, Feb 21, 2017

A problem people still might be seeing (with source maps when global detection is not disabled and variables such as global are found (and with debug: true), as well as the presence of a simple transform like uglifyify) is the Windows-specific issue at https://github.com/thlorenz/combine-source-map/pull/23

I’m adding further details below as a record (since it was little fun to debug!), but the PR already addresses the concern succinctly.

If the PR is still not accepted after my reminder, I think browserify ought to depend on the PR’s fork of combine-source-map (or browserify’s own copy of it) to resolve this (via updates or forks of insert-module-globals and browser-pack, the dependencies which browserify directly includes and which both (problematically) utilize the unfixed combine-source-map).


I am attempting to use node-browserify with uglifyify to handle minification while preserving info about source files to source maps.

(I’m also adding my own build of mapstraction to save the map to an external file (while being able to deal with base and relative paths) though this latter plugin only does anything of substance after its stream ends and that only occurs after the problem mentioned below.)

browserify({
    entries: 'index.js',
    standalone: 'Typeson',
    debug: true // Needed by mapstraction to extract source map
}).transform({global: true}, 'uglifyify').plugin(
    mapstraction, {_: ['dist/all.js.map']}
).bundle().pipe(
    fs.createWriteStream('dist/all.js')
);

Since I did not add detectGlobals: false, insert-module-globals will be invoked. This creates a through stream whose end calls a function closeOver which combines this stream’s chunks and invokes combine-source-map’s create (which just builds a Combiner) and then invokes the Combiner’s addFile with these source contents, and in so doing gets its source converted into a map as such: var existingMap = resolveMap(opts.source);.

The map then gets passed to Combiner.prototype._addExistingMap which copies the map var mappings = mappingsFromMap(existingMap); where mappingsFromMap refers to lib/mappings-from-map.

Later in Combiner.prototype._addExistingMap the following is called (though the code preceding it invoking this.generator.addSourceContent is also affected because of its use of rebaseRelativePath):

this.generator.addMappings(
      rebaseRelativePath(sourceFile, null, mapping.source), [mapping], offset);

In my case, sourceFile is types/errors.js while mapping.source is errors.js and when it is resolved, it becomes types\errors.js, so that is the mapping that is added (with Windows backslashes).

Later, when browserify continues its normal work unrelated to inserting globals, apparently since we have debug enabled, Browserify.prototype._debug gets called, including with this line:

row.sourceFile = relativePath(basedir, row.file)
                .replace(/\\/g, '/');

Although a Windows-style path is present in row.file (C:\<path to my repos>\typeson-registry\types\errors.js), the conversion to a relative path with the backslashes escaped leads row.sourceFile to getting a non-Windows path types/errors.js. The row is added to the stream and somehow browser-pack (which had been invoked earlier by browserify) gets its write method invoked with this row and it then invokes addFile (on the earlier created instance of combine-source-map) with an object including the non-Windows row.sourceFile path.

The above-mentioned _addExistingMap method from combine-source-map thus gets called again, calling addSourceContent (and addMappings) on an earlier created inline-source-map generator and to determine which path to supply (and determine what file if any ends up getting added).

Before supplying the arguments, however, _addExistingMap will invoke rebaseRelativePath to check whether the currently supplied file (the non-Windows one in this case) matches any of the previous existing ones (which it should since it has been added already albeit in Windows form).

Since the code within rebaseRelativePath of combine-source-map does a mere check without normalization of if (sourceFile === relativeRootedPath ||, there is a failure to match due to the difference in slashes. This causes the problem that the following line, return path.join(path.dirname(sourceFile), relativeRootedPath); is run which effectively adds another directory onto the path (e.g., so my file, types/errors.js mistakenly becomes types/types/errors.js in the source map).

The PR details another issue whereby non-recognition can also occur because a file (e.g., from CoffeeScript or TypeScript) is not recognized with its converted extension.

0reactions
brettz9commented, Mar 19, 2017

While the Windows comparison issue is one that can now be fixed within combine-source-map, it appears the issue I was seeing with some sources not having a parent was related to setting commondir to false (where commondir otherwise no longer has any effect–see #1075). I believe this option therefore ought to be removed or, if there is a reason why one would still need it (as when set to false, it currently causes / to be passed as insert-module-globals’s basedir in place of opts.basedir/cwd) renamed.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Sourcemaps are broken on Webpack 2 when you use ES6 ...
Before, I was trying to export a sourcemap, upload it to sentry, and not host it publicly. Got it working by just using...
Read more >
VS Code: "Breakpoint ignored because generated code not ...
I have generated the js.map files by running the tsc --sourcemap app.ts command. After all of those steps when I set a breakpoint...
Read more >
4 Reasons Why Your Source Maps are Broken - Sentry Blog
4 Reasons Why Your Source Maps are Broken · Missing or incorrect source map directive · Missing original source files · Bad source...
Read more >
Using Source Maps with TypeScript
Have you heard of Source Maps? Source Maps are an idea that has come out of Mozilla for addressing the debugging issues that...
Read more >
source-map | Yarn - Package Manager
MAX_SAFE_INTEGER ). It can now only handle them up to 2^32 - 1 . Breaking change: The source-map library now uses modern ECMAScript-isms:...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found