1.0.6 • Published 10 years ago

webpack-basic-sourcemap v1.0.6

Weekly downloads
2
License
MIT
Repository
github
Last release
10 years ago

webpack-basic-sourcemap

Parses module start-lines in bundle, embeds the info into the JS, then adds an \<Error>.Stack getter which calculates the original files/lines.

It's an alternative to regular source-maps, for when you need the source stack-traces in the JS code itself, and synchronously.

Notes

Transpilers should retain line-breaks

If you're using a transpiler in Webpack, you need to make sure it's set to retain the line-breaks of the original files.

For Babel, this means creating a .babelrc file with:

	"retainLines":true

Usage

1) Run npm install --save webpack-basic-sourcemap.
2) Add the following to your webpack.config file:

var WebpackBasicSourcemap = require("webpack-basic-sourcemap");
// ...
// module.exports = {
// ...
	plugins: [
		new WebpackBasicSourcemap(),
// ...
//};

3) Add the following to your JS start file:

// general polyfills
Object.defineProperty(Object.prototype, "Props", {enumerable: false, get: function() {
	var result = [];
	var i = 0;
	for (var propName in this)
		result.push({index: i++, name: propName, value: this[propName]});
	return result;
};
Object.defineProperty(Array.prototype, "Last", {enumerable: false, value: function(matchFunc = null) {
	if (matchFunc) {
        for (var i = this.length - 1; i >= 0; i--)
            if (matchFunc.call(this[i], this[i]))
                return this[i];
        return null;
    }
    return this[this.length - 1];
}});

function GetSourceStackEntryInfo(bundleName, bundleLine) {
	var bundle_modStartLinesInBundle = window["ModuleFileStartLines_" + bundleName];
	if (bundle_modStartLinesInBundle == null)
		return {modulePath: `[Can't find bundle with name: ${bundleName}]`, moduleFileName: `[Can't find bundle with name: ${bundleName}]`};
    var module = bundle_modStartLinesInBundle.Props.Last(a=>a.value <= bundleLine);
	if (module == null)
		return {modulePath: `[Can't find module for bundle ${bundleName}, line: ${bundleLine}]`,
			moduleFileName: `[Can't find module for bundle ${bundleName}, line: ${bundleLine}]`};
	
	var {name: modulePath, value: moduleStartLine} = module;
	var moduleFileName = modulePath.substr(modulePath.lastIndexOf("/") + 1);
	var moduleLine = bundleLine - moduleStartLine;
	return {modulePath, moduleFileName, moduleLine};
}
// gets the source stack-trace of the error (i.e. the stack-trace as it would be without the js-files being bundled into one)
Object.defineProperty(Error.prototype, "Stack", {enumerable: false, get: function() {
	var options = {
		bundlePath: true, // turn off for just file-name
		modulePath: true, // turn off for just file-name
	};

	var rawStack = this.stack;
	var oldLines = rawStack.split("\n");
	var newLines = oldLines.map(oldLine=> {
		let lineParts = oldLine.match(/^(.+?)\((.+?\.js):([0-9]+)(?::([0-9]+))?\)$/);
		if (lineParts == null) return oldLine;

		let [, beforeText, bundlePath, bundleLine, bundleColumn] = lineParts;
		let bundleFileName = bundlePath.substring(bundlePath.lastIndexOf("/") + 1);
		let bundleName = bundleFileName.substring(0, bundleFileName.lastIndexOf("."));

		let {modulePath, moduleFileName, moduleLine} = GetSourceStackEntryInfo(bundleName, bundleLine);
		return `${beforeText}(${(options.bundlePath ? encodeURI(bundlePath) : bundleFileName)}:${bundleLine}${bundleColumn ? ":" + bundleColumn : ""})${""
				} (${(options.modulePath ? "file:///" + encodeURI(modulePath) : moduleFileName)}:${moduleLine}${bundleColumn ? ":" + bundleColumn : ""})`;
	});
	return newLines.join("\n");
}});

4) Whenever you need the source stack-trace of an error, just call:

error.Stack

Alternatives

If you don't need the source stack-trace synchronously, you can use a library that calculates source stack-traces from regular source-maps: (though this takes longer)

1.0.6

10 years ago

1.0.5

10 years ago

1.0.4

10 years ago

1.0.3

10 years ago

1.0.2

10 years ago

1.0.1

10 years ago

1.0.0

10 years ago