An introduction to�Source Maps
NICOLÒ RIBAUDO
@nicolo-ribaudo
@NicoloRibaudo
https://nicr.dev
https://nicr.dev
2
NICOLÒ RIBAUDO
in collaboration with
https://nicr.dev
What are Source Maps?
3
https://nicr.dev
JavaScript is a compiled programming language
4
https://nicr.dev
5
User.ts
export class User {
@signal name;
constructor(name) {
this.name = name;
}
}
App.tsx
import { User } from "./User.ts";
export function App(
props: {user: User}
) {
return <div>
Hello {props.user.name}
</div>;
}
import _applyDecs from "@babel/runt…
�class User {
static {
[_init_name, _init_extra_name] …
}
name = _init_name(this);
constructor(name) {
_init_extra_name(this);
this.name = name;
}
}
import { User } from "./User.ts";
import { jsxs as _jsxs } from "preact/jsx-runtime";
export function App(props) {
return /*#__PURE__*/_jsxs("div", {
children: [
"Hello ",
props.user.name
]
});
}
function _applyDecs(targetClass, clas…
var symbolMetadata = Symbol.metadata || …
var defineProperty = Object.defineProperty;
var create = Object.create;
var metadata;
// Use both as and satisfies to ensure tha…
var existingNonFields = [create(null), cret…
var hasClassDecs = classDecs.length;
// This is a temporary variable for smaller…
var _;
function createRunInitializers(initializers…
return function (thisArg, value) {
if (useStaticThis) {
value = thisArg;
thisArg = targetClass;
}
for (var i = 0; i < initializers.length…
value = initializers[i].apply(thisArg…
bundle.js
class e{static{[_init_name,_init_extra_name
]=function(e,t,n,r,i,o){var a,c,s,u,l,f,d,h=
Symbol.metadata||Symbol.for("Symbol.metadata"),m=Object.defineProperty,p=Object.create,v=[p(null),p(null)],g=t.length;function b(t,n,r)
{return function(i,o){n&&(o=i,i=e);for(var a=0;a<t.length;a++)o=t[a].apply(i,r?[o]:[]);return r?o:i}}function y(e,t,n,r){if("function
"!=typeof e&&(r||void 0!==e))throw new TypeEr
ror(t+" must "+(n||"be")+" a function"+(r?"":
" or undefined"));return e}function _(e,t,n,
r,i,o,s,u,l,f,d){function h(e){if(!d(e))throw new TypeError("Attempted to access private el
ement on non-instance")}var p=[].concat(t[0])
,g=t[3],_=!s,w=1===i,j=3===i,E=4===i,x=2===i;function O(t,n,r){return function(i,o){retu…
https://nicr.dev
The code you write is not the code you run
6
https://nicr.dev
How do you debug it?
7
https://nicr.dev
8
1 class State {
2 get isLoggedIn() {
3 return true;
4 }
5 get isAdmin() {
6 return false;
7 }
8 }
9
10 function canReadNames(state) {
11 console.log("Is logged in?", state.isLoggedIn);
12 return state.isLoggedIn && state.isAdmin;
13 }
14
15 const state = new State();
16 console.log("Can read names?", canReadNames());
https://nicr.dev
9
1 class S {
2 get isLoggedIn() {return true;}
3 get isAdmin() {return false;}
4 }
5 function n(state) {console.log("Is logged in?", state.isLoggedIn);ret…
6 const s = new S();
7 console.log("Can read names?", n());
https://nicr.dev
Source maps let devtools map the running code to the original code
10
https://nicr.dev
11
1 class State {
2 get isLoggedIn() {
3 return true;
4 }
5 get isAdmin() {
6 return false;
7 }
8 }
9
10 function canReadNames(state) {
11 console.log("Is logged in?", state.isLoggedIn);
12 return state.isLoggedIn && state.isAdmin;
13 }
14
15 const state = new State();
16 console.log("Can read names?", canReadNames());
https://nicr.dev
Not just for JavaScript!
12
https://nicr.dev
Anatomy of a�Source Map
13
https://nicr.dev
14
1 {
2 "version": 3,
3 "file": "main.js",
4 "names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
5 "sources": [
6 "../src/main.ts"
7 ],
8 "sourcesContent": [
9 "interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
10 ],
11 "mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
12 }
https://nicr.dev
15
1 {
2 "version": 3,
3 "file": "main.js",
4 "names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
5 "sources": [
6 "../src/main.ts"
7 ],
8 "sourcesContent": [
9 "interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
10 ],
11 "mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
12 }
{
"version": 3,
"file": "main.js",
"names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
"sources": [
"../src/main.ts"
],
"sourcesContent": [
"interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
],
"mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
}
https://nicr.dev
16
1 {
2 "version": 3,
3 "file": "main.js",
4 "names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
5 "sources": [
6 "../src/main.ts"
7 ],
8 "sourcesContent": [
9 "interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
10 ],
11 "mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
12 }
{
"file": "main.js",
"names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
"sources": [
"../src/main.ts"
],
"sourcesContent": [
"interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
],
"mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
}
https://nicr.dev
17
1 {
2 "version": 3,
3 "file": "main.js",
4 "names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
5 "sources": [
6 "../src/main.ts"
7 ],
8 "sourcesContent": [
9 "interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
10 ],
11 "mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
12 }
{
"version": 3,
"names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
"sources": [
"../src/main.ts"
],
"sourcesContent": [
"interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
],
"mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
}
https://nicr.dev
18
1 {
2 "version": 3,
3 "file": "main.js",
4 "names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
5 "sources": [
6 "../src/main.ts"
7 ],
8 "sourcesContent": [
9 "interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
10 ],
11 "mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
12 }
{
"version": 3,
"file": "main.js",
"AmazingPet","name","title","class_Pet","prototype","sayHi","console…
"sources": [
"../src/main.ts"
],
"sourcesContent": [
"interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
],
"mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
}
https://nicr.dev
19
1 {
2 "version": 3,
3 "file": "main.js",
4 "names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
5 "sources": [
6 "../src/main.ts"
7 ],
8 "sourcesContent": [
9 "interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
10 ],
11 "mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
12 }
{
"version": 3,
"file": "main.js",
"names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
"sourcesContent": [
"interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
],
"mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
}
https://nicr.dev
sources
20
dist/main.js
function class_AmazingPet({
name,
title
}) {
this.name = name;
this.title = title;
}
class_AmazingPet.prototype.sayHi = fu…
console.log(`Hello, I'm ${this.titl…
};
const timmy = new class_AmazingPet({
name: "Timmy",
… … …
src/main.ts
"sources": [
"../src/main.ts"
],
https://nicr.dev
sources
21
dist/main.js
function class_AmazingPet({
name,
title
}) {
this.name = name;
this.title = title;
}
class_AmazingPet.prototype.sayHi = fu…
console.log(`Hello, I'm ${this.titl…
};
const timmy = new class_AmazingPet({
name: "Timmy",
… … …
src/main.ts
"sources": [
"../src/main.ts",
"../src/other.js"
],
src/other.js
https://nicr.dev
22
1 {
2 "version": 3,
3 "file": "main.js",
4 "names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
5 "sources": [
6 "../src/main.ts"
7 ],
8 "sourcesContent": [
9 "interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
10 ],
11 "mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
12 }
{
"version": 3,
"file": "main.js",
"names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
"sources": [
"../src/main.ts"
],
"mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
}
https://nicr.dev
sourcesContent
23
dist/main.js
function class_AmazingPet({
name,
title
}) {
this.name = name;
this.title = title;
}
class_AmazingPet.prototype.sayHi = fu…
console.log(`Hello, I'm ${this.titl…
};
const timmy = new class_AmazingPet({
name: "Timmy",
… … …
src/main.ts
interface PetConfig {
name: string;
title: string;
}
class AmazingPet {
declare name: string;
declare title: string;
constructor({ name, title }: PetCon…
this.name = name;
this.title = title;
… … …
"sourcesContent": [
"interface PetConfig {\n …
],
https://nicr.dev
sourcesContent
24
dist/main.js
function class_AmazingPet({
name,
title
}) {
this.name = name;
this.title = title;
}
class_AmazingPet.prototype.sayHi = fu…
console.log(`Hello, I'm ${this.titl…
};
const timmy = new class_AmazingPet({
name: "Timmy",
… … …
src/main.ts
src/other.js
"sourcesContent": [
"interface PetConfig {\n …
"// some other file\n// c…
],
interface PetConfig {
name: string;
title: string;
}
class AmazingPet {
… … …
// some other file
// containing many
// interesting things
console.log("Hi!");
https://nicr.dev
sources and sourcesContent let devtools show the original files
25
https://nicr.dev
How to they know that
this point
was originally this one?
26
8 class_AmazingPet.prototype.sayHi = function sayHi() {
9 console.log(`Hello, I'm ${this.title} ${this.name}`);
10 };
15 sayHi() {
16 console.log(`Hello, I'm ${this.title} ${this.name}`);
17 }
https://nicr.dev
27
1 {
2 "version": 3,
3 "file": "main.js",
4 "names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
5 "sources": [
6 "../src/main.ts"
7 ],
8 "sourcesContent": [
9 "interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
10 ],
11 "mappings": "AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAA…
12 }
{
"version": 3,
"file": "main.js",
"names": ["AmazingPet","name","title","class_Pet","prototype","sayHi","console…
"sources": [
"../src/main.ts"
],
"sourcesContent": [
"interface PetConfig {\n name: string;\n title: string;\n}\n\nclass Amazin…
],
}
https://nicr.dev
28
"mappings":"AAKA,SAAMA,gBAAUA,CAIF;EAAEC,IAAI;EAAEC;AAAiB,CAAC,EAAE;EACtC,IAAI,CAACD,IAAI,GAAGA,IAAI;EAChB,IAAI,CAACC,KAAK,GAAGA,KAAK;AACpB;AAACC,SAAA,CAAAC,SAAA,CAAAC,KAAA,GAED,SAAAA,MAAA,EAAQ;EACNC,OAAO,CAACC,GAAG,CAAC,cAAc,IAAI,CAACL,KAAK,IAAI,IAAI,CAACD,IAAI,EAAE,CAAC;AACtD,CAAC;AAGH,MAAMO,KAAK,GAAG,IAAIR,SAAG,CAAC;EAAEC,IAAI,EAAE,OAAO;EAAEC,KAAK,EAAE;AAAK,CAAC,CAAC;AACrDM,KAAK,CAACH,KAAK,CAAC,CAAC"
https://nicr.dev
29
1 function class_AmazingPet({
2 name,
3 title
4 }) {
5 this.name = name;
6 this.title = title;
7 }
8 class_AmazingPet.prototype.sayHi = function sayH…
9 console.log(`Hello, I'm ${this.title} ${this.n…
10 };
11 const timmy = new class_AmazingPet({
12 name: "Timmy",
13 title: "Dr"
14 });
15 timmy.sayHi();
AAKA,SAAMA,gBAAUA,CAIF;�EAAEC,IAAI;�EAAEC;�AAAiB,CAAC,EAAE;�EACtC,IAAI,CAACD,IAAI,GAAGA…;
EAChB,IAAI,CAACC,KAAK,GAAGA…;
AACpB;
AAACC,SAAA,CAAAC,SAAA,CAAAC…;
EACNC,OAAO,CAACC,GAAG,CAAC,…;
AACtD,CAAC;
AAGH,MAAMO,KAAK,GAAG,IAAIR,…;
EAAEC,IAAI,EAAE,OAAO;
EAAEC,KAAK,EAAE;
AAAK,CAAC,CAAC;
AACrDM,KAAK,CAACH,KAAK,CAAC,…
https://nicr.dev
30
https://nicr.dev
The Source Map standard
31
https://nicr.dev
32
2011–2023
https://nicr.dev
33
2024
https://nicr.dev
Why a standard?
34
https://nicr.dev
Source Map in TC39: goals
35
https://nicr.dev
New Source Map features
36
https://nicr.dev
"ignoreList": […]
37
1 {
2 "version": 3,
3 "file": "bundle.js",
4 "names": […],
5 "sources": [
6 "../src/main.ts",
7 "../src/utils.ts",
8 "../node_modules/some-lib/index.js",
9 "bundler-iternal://helpers"
10 ],
11 "ignoreList": [2, 3],
… … …
Ignore some source files in stack traces and debuggers
https://nicr.dev
Scopes proposal
Source maps allow mapping locations and� variable names from the final code to the original source
38
Is this enough?
https://nicr.dev
Scopes proposal
39
1 function logIfBig(num) {
2 const treeshold = 2;
3 if (num > treeshold) {
4 console.log("big: " + num);
5 }
6 }
7 export function run(val) {
8 for (let i = 0; i < val; i++) {
9 logIfBig(i);
10 }
11 }
src/main.js
1 export function run(v) {
2 for(let i=0;i<v;i++) {
3 if (i>2) {
4 console.log("big: " + i);
5 }
6 }
7 }
dist/main.min.js
logIfBig is inlined inside run
treeshold is replaced with 2
https://nicr.dev
An introduction�Source Maps
NICOLÒ RIBAUDO
@nicolo-ribaudo
@NicoloRibaudo
https://nicr.dev
https://nicr.dev