# Using original JS source maps

**URL:** https://clojureverse.org/t/using-original-js-source-maps/6469
**Category:** shadow-cljs
**Created:** [August 31, 2020, 7:00pm UTC](https://clojureverse.org/t/using-original-js-source-maps/6469 "2020-08-31T19:00:28Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![mapidentity](https://clojureverse.org/letter_avatar_proxy/v4/letter/m/ce73a5/32.png) [@mapidentity](https://clojureverse.org/u/mapidentity)
#### Post date: [August 31, 2020, 7:00pm UTC](https://clojureverse.org/t/using-original-js-source-maps/6469/1 "2020-08-31T19:00:28Z")

</div>

shadow-cljs allows using arbitrary JS files as documented in [12.2.3. JavaScript Dialects](https://shadow-cljs.github.io/docs/UsersGuide.html#_javascript_dialects). For source maps, shadow-cljs appears to create new ones from the generated (and included) JS files. Is it possible to pass the source maps from the original compilation (e.g. babel or other tool) through to the shadow-cljs output? This could be related to [this GitHub issue](https://github.com/thheller/shadow-cljs/issues/127), but I’m not quite sure if this is the same use case. Also this issue is quite old (2017), perhaps there’s another way to solve this. Thanks!

---

<div class="post-metadata">

### Author: ![thheller](https://clojureverse.org/user_avatar/clojureverse.org/thheller/32/534_2.png) [@thheller](https://clojureverse.org/u/thheller)
#### Post date: [August 31, 2020, 7:59pm UTC](https://clojureverse.org/t/using-original-js-source-maps/6469/2 "2020-08-31T19:59:49Z")

</div>

Unfortunately this is not working properly. I haven’t figured out how to get it to work reliably. It is supposed to work automatically assuming the generated JS files have either inlined source maps or the source maps available in the same directory and properly linked via `sourceMappingUrl`. It does however not seem to work for JS files, not sure why. It works fine for CLJS files.

---

<div class="post-metadata">

### Author: ![mapidentity](https://clojureverse.org/letter_avatar_proxy/v4/letter/m/ce73a5/32.png) [@mapidentity](https://clojureverse.org/u/mapidentity)
#### Post date: [September 1, 2020, 10:55am UTC](https://clojureverse.org/t/using-original-js-source-maps/6469/3 "2020-09-01T10:55:04Z")

</div>

Thanks Thomas! Could this be path related? If I include

```auto
//# sourceMappingURL=src/gen/example.js.map

```

it does try and look for the file. If for example I give an illegal path like `src/gen/idontexist.js.map` an error is given on recompilation:

```auto
Failed to resolve sourcemap at src/gen/idontexist.js.map svelte.js.map: src/gen/idontexist.js.map

```

which appears to be an error coming from the Google Closure compiler. Note that generated js and map file are both in `src/gen`. So I’d actually expect adding just `//# sourceMappingURL=example.js.map` to the generated js file (without the src/gen path).

edit: formatting.

---

<div class="post-metadata">

### Author: ![mapidentity](https://clojureverse.org/letter_avatar_proxy/v4/letter/m/ce73a5/32.png) [@mapidentity](https://clojureverse.org/u/mapidentity)
#### Post date: [September 2, 2020, 6:27pm UTC](https://clojureverse.org/t/using-original-js-source-maps/6469/4 "2020-09-02T18:27:23Z")

</div>

I think I found a way to solve this; very much by trial and error and works in Chrome and Firefox (not in Safari for unknown reasons). Slight modification to the function `convert-sources*` in source file `shadow.build.closure.clj` is needed (used version 2.11.1). I’ve added the following settings to the compiler options `co`:

```clojure
(.setApplyInputSourceMaps co true)
(.setSourceMapIncludeSourcesContent co true)

```

This part of the code needed to be removed to have the original source map contents included:

```clojure
(.reset source-map)

```

And this part doesn’t seem to do anything anymore (and could be removed?)

```clojure
;; for sourcesContent
(.addSourceFile (.getName source-file) (.getCode source-file))

```

I have tested this with transpiled JS sources which include source map with original file contents (a comment added at the end of the generated JS file, e.g. `//# sourceMappingURL=data:application/json;base64,ewogI...`) which appears to be working well.

Unfortunately I’m not intimately familiar with the Google Closure compiler, so it’s very hard for me to tell if these are proper changes and don’t break existing stuff. If you’d like, I’ll gladly make a PR for this to review / discuss.

Thanks!

---

<div class="post-metadata">

### Author: ![thheller](https://clojureverse.org/user_avatar/clojureverse.org/thheller/32/534_2.png) [@thheller](https://clojureverse.org/u/thheller)
#### Post date: [September 2, 2020, 7:40pm UTC](https://clojureverse.org/t/using-original-js-source-maps/6469/5 "2020-09-02T19:40:10Z")

</div>

`(.reset source-map)` must be called. Otherwise it’ll fail when trying to generate the source map for another file.

You might be onto something though since I already [re-add the sources](https://github.com/thheller/shadow-cljs/blob/28169be104149e496b31bad443be7ecb6d16cd4a/src/main/shadow/build/closure.clj#L1098) when generating source maps for optimized sources. That might be all thats missing.

---

<div class="post-metadata">

### Author: ![thheller](https://clojureverse.org/user_avatar/clojureverse.org/thheller/32/534_2.png) [@thheller](https://clojureverse.org/u/thheller)
#### Post date: [September 2, 2020, 7:46pm UTC](https://clojureverse.org/t/using-original-js-source-maps/6469/6 "2020-09-02T19:46:23Z")

</div>

Hmm no luck. Can’t get Chrome to display the actual sources. Can you share the source mapped file you tried this with? Maybe I’m doing something wrong when generating it.

---

<div class="post-metadata">

### Author: ![mapidentity](https://clojureverse.org/letter_avatar_proxy/v4/letter/m/ce73a5/32.png) [@mapidentity](https://clojureverse.org/u/mapidentity)
#### Post date: [September 2, 2020, 7:55pm UTC](https://clojureverse.org/t/using-original-js-source-maps/6469/7 "2020-09-02T19:55:10Z")

</div>

```javascript
/* example.svelte generated by Svelte v3.24.1 */
import {
	SvelteComponentDev,
	add_location,
	append_dev,
	attr_dev,
	detach_dev,
	dispatch_dev,
	element,
	globals,
	init,
	insert_dev,
	listen_dev,
	noop,
	safe_not_equal,
	set_data_dev,
	space,
	text,
	validate_slots
} from "svelte/internal";

const { Error: Error_1 } = globals;
import { getmessage } from "goog:cljsvelte.utils";
const file = "example.svelte";

function add_css() {
	var style = element("style");
	style.id = "svelte-klh1a0-style";
	style.textContent = ".btn.svelte-klh1a0{color:cadetblue}\n/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhhbXBsZS5zdmVsdGUiLCJzb3VyY2VzIjpbImV4YW1wbGUuc3ZlbHRlIl0sInNvdXJjZXNDb250ZW50IjpbIjxzY3JpcHQ+XG4gIGltcG9ydCB7IGdldG1lc3NhZ2UgfSBmcm9tIFwiZ29vZzpjbGpzdmVsdGUudXRpbHNcIjtcbiAgZXhwb3J0IGxldCBjb3VudDtcblxuICAkOiBpZiAoY291bnQgPj0gMTApIHtcbiAgICBhbGVydChgY291bnQgaXMgZGFuZ2Vyb3VzbHkgaGlnaCFgKTtcbiAgICBjb3VudCA9IDk7XG4gIH1cblxuICBmdW5jdGlvbiBoYW5kbGVDbGljaygpIHtcbiAgICBjb3VudCArPSAxO1xuICAgIHRocm93IEVycm9yKFwiS2Fib29tXCIpO1xuICB9XG48L3NjcmlwdD5cblxuPHN0eWxlPlxuICAuYnRuIHtcbiAgICBjb2xvcjogY2FkZXRibHVlO1xuICB9XG48L3N0eWxlPlxuXG48YnV0dG9uIGNsYXNzPVwiYnRuXCIgb246Y2xpY2s9e2hhbmRsZUNsaWNrfT5cbiAgQ2xpY2tlZCB7Y291bnR9IHtjb3VudCA9PT0gMSA/ICd0aW1lJyA6ICd0aW1lcyd9IHtnZXRtZXNzYWdlKCl9XG48L2J1dHRvbj5cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFnQkUsSUFBSSxjQUFDLENBQUMsQUFDSixLQUFLLENBQUUsU0FBUyxBQUNsQixDQUFDIn0= */";
	append_dev(document.head, style);
}

function create_fragment(ctx) {
	let button;
	let t0;
	let t1;
	let t2;
	let t3_value = (/*count*/ ctx[0] === 1 ? "time" : "times") + "";
	let t3;
	let t4;
	let t5_value = getmessage() + "";
	let t5;
	let mounted;
	let dispose;

	const block = {
		c: function create() {
			button = element("button");
			t0 = text("Clicked ");
			t1 = text(/*count*/ ctx[0]);
			t2 = space();
			t3 = text(t3_value);
			t4 = space();
			t5 = text(t5_value);
			attr_dev(button, "class", "btn svelte-klh1a0");
			add_location(button, file, 21, 0, 306);
		},
		l: function claim(nodes) {
			throw new Error_1("options.hydrate only works if the component was compiled with the `hydratable: true` option");
		},
		m: function mount(target, anchor) {
			insert_dev(target, button, anchor);
			append_dev(button, t0);
			append_dev(button, t1);
			append_dev(button, t2);
			append_dev(button, t3);
			append_dev(button, t4);
			append_dev(button, t5);

			if (!mounted) {
				dispose = listen_dev(button, "click", /*handleClick*/ ctx[1], false, false, false);
				mounted = true;
			}
		},
		p: function update(ctx, [dirty]) {
			if (dirty & /*count*/ 1) set_data_dev(t1, /*count*/ ctx[0]);
			if (dirty & /*count*/ 1 && t3_value !== (t3_value = (/*count*/ ctx[0] === 1 ? "time" : "times") + "")) set_data_dev(t3, t3_value);
		},
		i: noop,
		o: noop,
		d: function destroy(detaching) {
			if (detaching) detach_dev(button);
			mounted = false;
			dispose();
		}
	};

	dispatch_dev("SvelteRegisterBlock", {
		block,
		id: create_fragment.name,
		type: "component",
		source: "",
		ctx
	});

	return block;
}

function instance($$self, $$props, $$invalidate) {
	let { count } = $$props;

	function handleClick() {
		$$invalidate(0, count += 1);
		throw Error("Kaboom");
	}

	const writable_props = ["count"];

	Object.keys($$props).forEach(key => {
		if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(`<Example> was created with unknown prop '${key}'`);
	});

	let { $$slots = {}, $$scope } = $$props;
	validate_slots("Example", $$slots, []);

	$$self.$$set = $$props => {
		if ("count" in $$props) $$invalidate(0, count = $$props.count);
	};

	$$self.$capture_state = () => ({ getmessage, count, handleClick });

	$$self.$inject_state = $$props => {
		if ("count" in $$props) $$invalidate(0, count = $$props.count);
	};

	if ($$props && "$$inject" in $$props) {
		$$self.$inject_state($$props.$$inject);
	}

	$$self.$$.update = () => {
		if ($$self.$$.dirty & /*count*/ 1) {
			$: if (count >= 10) {
				alert(`count is dangerously high!`);
				$$invalidate(0, count = 9);
			}
		}
	};

	return [count, handleClick];
}

class Example extends SvelteComponentDev {
	constructor(options) {
		super(options);
		if (!document.getElementById("svelte-klh1a0-style")) add_css();
		init(this, options, instance, create_fragment, safe_not_equal, { count: 0 });

		dispatch_dev("SvelteRegisterComponent", {
			component: this,
			tagName: "Example",
			options,
			id: create_fragment.name
		});

		const { ctx } = this.$$;
		const props = options.props || {};

		if (/*count*/ ctx[0] === undefined && !("count" in props)) {
			console.warn("<Example> was created without expected prop 'count'");
		}
	}

	get count() {
		throw new Error_1("<Example>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
	}

	set count(value) {
		throw new Error_1("<Example>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
	}
}

export default Example;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiZXhhbXBsZS5zdmVsdGUiXSwic291cmNlc0NvbnRlbnQiOlsiPHNjcmlwdD5cbiAgaW1wb3J0IHsgZ2V0bWVzc2FnZSB9IGZyb20gXCJnb29nOmNsanN2ZWx0ZS51dGlsc1wiO1xuICBleHBvcnQgbGV0IGNvdW50O1xuXG4gICQ6IGlmIChjb3VudCA+PSAxMCkge1xuICAgIGFsZXJ0KGBjb3VudCBpcyBkYW5nZXJvdXNseSBoaWdoIWApO1xuICAgIGNvdW50ID0gOTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGhhbmRsZUNsaWNrKCkge1xuICAgIGNvdW50ICs9IDE7XG4gICAgdGhyb3cgRXJyb3IoXCJLYWJvb21cIik7XG4gIH1cbjwvc2NyaXB0PlxuXG48c3R5bGU+XG4gIC5idG4ge1xuICAgIGNvbG9yOiBjYWRldGJsdWU7XG4gIH1cbjwvc3R5bGU+XG5cbjxidXR0b24gY2xhc3M9XCJidG5cIiBvbjpjbGljaz17aGFuZGxlQ2xpY2t9PlxuICBDbGlja2VkIHtjb3VudH0ge2NvdW50ID09PSAxID8gJ3RpbWUnIDogJ3RpbWVzJ30ge2dldG1lc3NhZ2UoKX1cbjwvYnV0dG9uPlxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O1NBQ1csVUFBVSxRQUFRLHNCQUFzQjs7Ozs7Ozs7Ozs7Ozs7OzJCQXFCaEMsR0FBSyxRQUFLLENBQUMsR0FBRyxNQUFNLEdBQUcsT0FBTzs7O2dCQUFHLFVBQVU7Ozs7Ozs7Ozt1QkFBbkQsR0FBSzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzBEQURjLEdBQVc7Ozs7O3VEQUM5QixHQUFLO2tFQUFHLEdBQUssUUFBSyxDQUFDLEdBQUcsTUFBTSxHQUFHLE9BQU87Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O09BcEJwQyxLQUFLOztVQU9QLFdBQVc7a0JBQ2xCLEtBQUssSUFBSSxDQUFDO1FBQ0osS0FBSyxDQUFDLFFBQVE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FQdEIsQ0FBQyxNQUFNLEtBQUssSUFBSSxFQUFFO0lBQ2hCLEtBQUs7b0JBQ0wsS0FBSyxHQUFHLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OyIsImZpbGUiOiJtb2R1bGUkZXhhbXBsZV9zdmVsdGUuanMifQ==

```

---

<div class="post-metadata">

### Author: ![mapidentity](https://clojureverse.org/letter_avatar_proxy/v4/letter/m/ce73a5/32.png) [@mapidentity](https://clojureverse.org/u/mapidentity)
#### Post date: [September 2, 2020, 8:11pm UTC](https://clojureverse.org/t/using-original-js-source-maps/6469/8 "2020-09-02T20:11:26Z")

</div>

whipped up a quick repo, see GitHub. Runs with `npm run dev`.

---

<div class="post-metadata">

### Author: ![thheller](https://clojureverse.org/user_avatar/clojureverse.org/thheller/32/534_2.png) [@thheller](https://clojureverse.org/u/thheller)
#### Post date: [September 2, 2020, 8:53pm UTC](https://clojureverse.org/t/using-original-js-source-maps/6469/9 "2020-09-02T20:53:33Z")

</div>

Just pushed a rather [hacky attempt](https://github.com/thheller/shadow-cljs/commit/43a229c6f797030d2bb39382ab1ead465d36c46c) to fix this. Needs more testing but it appears to work. I’ll probably make a release with this soon. Or you can just take the `closure.clj` in `master` and try it directly, like you have in that repo.

---

<div class="post-metadata">

### Author: ![mapidentity](https://clojureverse.org/letter_avatar_proxy/v4/letter/m/ce73a5/32.png) [@mapidentity](https://clojureverse.org/u/mapidentity)
#### Post date: [September 2, 2020, 9:26pm UTC](https://clojureverse.org/t/using-original-js-source-maps/6469/10 "2020-09-02T21:26:53Z")

</div>

I’m getting some unexpected behavior in terms of mapping alignment. i.e., positions in source file is not quite where I’d expect them (dev, haven’t looked at prod yet). I’ll investigate more into this, could very well be related to my project setup and not related to GCC/Shadow. Other than that, seems to work!

---

<div class="post-metadata">

### Author: ![system](https://clojureverse.org/uploads/default/original/2X/5/51079bf9e4b7d9466242c06cf1e43b9f8bd6da14.png) [@system](https://clojureverse.org/u/system)
#### Post date: [March 4, 2021, 9:26am UTC](https://clojureverse.org/t/using-original-js-source-maps/6469/11 "2021-03-04T09:26:57Z")

</div>

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.
