-
Notifications
You must be signed in to change notification settings - Fork 16
/
source-map.bs
1164 lines (968 loc) · 57 KB
/
source-map.bs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<pre class='metadata'>
Title: Source Map Format Specification
H1: Source Map
Shortname: source-map
Level: none
Status: STAGE0
URL: https://tc39.es/source-map/
Repository: https://github.com/tc39/source-map/
Issue Tracking: GitHub Issues https://github.com/tc39/source-map/issues
Test Suite: https://github.com/tc39/source-map-tests
Editor Term: Editor, Editors
Editor: Asumu Takikawa, Igalia
Former Editor: Victor Porof, Google
Former Editor: John Lenz, Google
Former Editor: Nick Fitzgerald, Mozilla
Previous Version: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#
Repository: source-map/source-map-spec
Abstract: This Ecma standard defines the Source Map format, used for mapping transpiled source code back to the original sources.
No Abstract: true
Markup Shorthands: markdown yes
Group: tc39
Boilerplate: references no
</pre>
<!-- Uncomment the next line when generating the PDF version of the spec -->
<!-- <link rel="stylesheet" href="./ecma-style/ecma.css"> -->
<pre class=link-defaults>
spec:html; type:element;
text:a
text:script
text:style
text:title
text:link
spec:fetch; type:dfn; for:/;
text:request
text:response
spec:url; type:dfn; for:/; text:url
spec:infra; type:dfn;
text:list
for:list; text:for each
</pre>
<pre class="anchors">
urlPrefix:https://tc39.es/ecma262/#; type:dfn; spec:ecmascript
url:sec-lexical-and-regexp-grammars; text:tokens
url:table-line-terminator-code-points; text:line terminator code points
url:sec-white-space; text: white space code points
url:prod-SingleLineComment; text:single-line comment
url:prod-MultiLineComment; text:multi-line comment
url:prod-MultiLineComment; text:multi-line comment
url:sec-regexpbuiltinexec; text:RegExpBuiltinExec
url:prod-Comment; text:Comment
url:prod-DivPunctuator; text:DivPunctuator
url:prod-HashbangComment; text:HashbangComment
url:prod-IdentifierName; text:IdentifierName
url:prod-LineTerminator; text:LineTerminator
url:prod-NumericLiteral; text:NumericLiteral
url:prod-Punctuator; text:Punctuator
url:prod-PrivateIdentifier; text:PrivateIdentifier
url:prod-RegularExpressionLiteral; text:RegularExpressionLiteral
url:prod-RightBracePunctuator; text:RightBracePunctuator
url:prod-StringLiteral; text:StringLiteral
url:prod-Template; text:Template
url:prod-TemplateSubstitutionTail; text:TemplateSubstitutionTail
url:prod-WhiteSpace; text:WhiteSpace
url:sec-ecmascript-language-lexical-grammar; text:ECMAScript Lexical Grammar
url:prod-Arguments; text:Arguments
url:prod-BindingIdentifier; text:BindingIdentifier
url:prod-ClassElementName; text:ClassElementName
url:prod-FormalParameters; text:FormalParameters
url:prod-FunctionDeclaration; text:FunctionDeclaration
url:prod-FunctionExpression; text:FunctionExpression
url:prod-Expression; text:Expression
url:prod-AsyncFunctionDeclaration; text:AsyncFunctionDeclaration
url:prod-AsyncFunctionExpression; text:AsyncFunctionExpression
url:prod-ArrowFormalParameters; text:ArrowFormalParameters
url:prod-ArrowFunction; text:ArrowFunction
url:prod-ArrowParameters; text:ArrowParameters
url:prod-AsyncArrowFunction; text:AsyncArrowFunction
url:prod-AsyncArrowBindingIdentifier; text:AsyncArrowBindingIdentifier
url:prod-GeneratorDeclaration; text:GeneratorDeclaration
url:prod-GeneratorExpression; text:GeneratorExpression
url:prod-MethodDefinition; text:MethodDefinition
url:prod-AsyncGeneratorDeclaration; text:AsyncGeneratorDeclaration
url:prod-AsyncGeneratorExpression; text:AsyncGeneratorExpression
url:prod-IdentifierReference; text:IdentifierReference
url:prod-LexicalDeclaration; text:LexicalDeclaration
url:prod-VariableStatement; text:VariableStatement
url:sec-parameter-lists; text:Parameter List
url:sec-syntactic-grammar; text:Syntactic Grammar
urlPrefix:https://webassembly.github.io/spec/core/; type:dfn; spec:wasm
url:binary/modules.html#binary-customsec; text:custom section
url:appendix/embedding.html#embed-module-decode; text:module_decode
</pre>
<pre class="biblio">
{
"VLQ": {
"href": "https://en.wikipedia.org/wiki/Variable-length_quantity",
"title": "Variable-length quantity",
"publisher": "Wikipedia",
"status": "reference article"
},
"base64": {
"href": "https://www.ietf.org/rfc/rfc4648.txt",
"id": "rfc4648",
"publisher": "IETF",
"status": "Standards Track",
"title": "The Base16, Base32, and Base64 Data Encodings"
},
"URL": {
"href": "https://url.spec.whatwg.org/",
"publisher": "WhatWG",
"status": "Living Standard",
"title": "URL Standard"
},
"EvalSourceURL": {
"href": "https://web.archive.org/web/20120814122523/http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/",
"publisher": "Firebug",
"status": "archive",
"title": "Give your eval a name with //@ sourceURL"
},
"ECMA-262": {
"href": "https://tc39.es/ecma262/",
"id": "esma262",
"publisher": "ECMA",
"status": "Standards Track",
"title": "ECMAScript® Language Specification"
},
"V2Format": {
"href": "https://docs.google.com/document/d/1xi12LrcqjqIHTtZzrzZKmQ3lbTv9mKrN076UB-j3UZQ/edit?hl=en_US",
"publisher": "Google",
"title": "Source Map Revision 2 Proposal"
},
"WasmNamesBinaryFormat": {
"href": "https://www.w3.org/TR/wasm-core-2/#names%E2%91%A2",
"publisher": "W3C",
"status": "Living Standard",
"title": "WebAssembly Names binary format"
}
}
</pre>
<h2 class="no-num" id="intro">Introduction</h2>
This Ecma Standard defines the Source Map Format, used for mapping transpiled source code back to the original sources.
The source map format has the following goals:
* Support source-level debugging allowing bidirectional mapping
* Support server-side stack trace deobfuscation
The document at [https://tc39.es/source-map/](https://tc39.es/source-map/) is the most accurate and
up-to-date source map specification. It contains the content of the most recently published snapshot
plus any modifications that will be included in the next snapshot.
If you want to get involved you will find more information at the [specification
repository](https://github.com/tc39/source-map).
The original source map format (v1) was created by Joseph Schorr for use by
Closure Inspector to enable source-level debugging of optimized JavaScript code
(although the format itself is language agnostic). However, as the size of the
projects using source maps expanded, the verbosity of the format started to
become a problem. The v2 format [[V2Format]] was created by trading some simplicity
and flexibility to reduce the overall size of the source map. Even with the
changes made with the v2 version of the format, the source map file size was
limiting its usefulness. The v3 format is based on suggestions made by
Pavel Podivilov (Google).
The source map format does not have version numbers anymore, and it is instead
hard-coded to always be "3".
<div style="display: none" id="copyright-before"></div>
<div style="display: none" id="copyright">
<p>COPYRIGHT NOTICE</p>
<p>© 2024 Ecma International</p>
<p>This document may be copied, published and distributed to others, and certain derivative works of it
may be prepared, copied, published, and distributed, in whole or in part, provided that the above
copyright notice and this Copyright License and Disclaimer are included on all such copies and
derivative works. The only derivative works that are permissible under this Copyright License and
Disclaimer are:</p>
<ol>
<li>works which incorporate all or portion of this document for the purpose of providing commentary
or explanation (such as an annotated version of the document),</li>
<li>works which incorporate all or portion of this document for the purpose of incorporating
features that provide accessibility,</li>
<li>translations of this document into languages other than English and into different formats
and</li>
<li>works by making use of this specification in standard conformant products by implementing (e.g.
by copy and paste wholly or partly) the functionality therein.</li>
</ol>
<p>However, the content of this document itself may not be modified in any way, including by
removing the copyright notice or references to Ecma International, except as required to translate
it into languages other than English or into a different format.</p>
<p>The official version of an Ecma International document is the English language version on the
Ecma International website. In the event of discrepancies between a translated version and the
official version, the official version shall govern.</p>
<p>The limited permissions granted above are perpetual and will not be revoked by Ecma
International or its successors or assigns.</p>
<p>This document and the information contained herein is provided on an "AS IS" basis and ECMA
INTERNATIONAL DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY
WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP RIGHTS OR ANY
IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.</p>
</div>
<div style="display: none" id="copyright-after"></div>
<!-- Use a script tag because bikeshed doesn't like <h1> tags -->
<script>document.write(`
<h1 id="pdf-title" style="display: none" id="print-title">Source Map specification</h1>
`)</script>
Scope {#scope}
==============
This Standard defines the source map format, used by different types of
developer tools to improve the debugging experience of code compiled to
JavaScript, WebAssembly, and CSS.
Conformance {#conformance}
==========================
A conforming source map document is a JSON document that conforms to the
structure detailed in this specification.
A conforming source map generator should generate documents which are
conforming source map documents, and can be decoded by the algorithms in this
specification without reporting any errors (even those which are specified as
optional).
A conforming source map consumer should implement the algorithms specified in this
specification for retrieving (where applicable) and decoding source map documents.
A conforming consumer is permitted to ignore errors or report them without
terminating where the specification indicates that an algorithm may
[=optionally report an error=].
References {#references}
========================
<!--
NOTE: This references section is manually generated because bikeshed assumes
that the references section should be un-numbered and we want to include
it as a numbered section. To generate it, use the following and then
copy the inner HTML contents:
<div data-fill-with="references"></div>
and replace [ with \[ to escape macros. Also add data-no-self-link="" to
each <dt> entry.
-->
<h3 class="no-num no-ref heading settled" id="normative"><span class="content">Normative References</span><a class="self-link" href="#normative"></a></h3>
<div class="no-ref">
<dl>
<dt id="biblio-ecmascript" data-no-self-link="">\[ECMASCRIPT]
</dt><dd><a href="https://tc39.es/ecma262/multipage/"><cite>ECMAScript Language Specification</cite></a>. URL: <a href="https://tc39.es/ecma262/multipage/">https://tc39.es/ecma262/multipage/</a>
</dd><dt id="biblio-encoding" data-no-self-link="">\[ENCODING]
</dt><dd>Anne van Kesteren. <a href="https://encoding.spec.whatwg.org/"><cite>Encoding Standard</cite></a>. Living Standard. URL: <a href="https://encoding.spec.whatwg.org/">https://encoding.spec.whatwg.org/</a>
</dd><dt id="biblio-fetch" data-no-self-link="">\[FETCH]
</dt><dd>Anne van Kesteren. <a href="https://fetch.spec.whatwg.org/"><cite>Fetch Standard</cite></a>. Living Standard. URL: <a href="https://fetch.spec.whatwg.org/">https://fetch.spec.whatwg.org/</a>
</dd><dt id="biblio-infra" data-no-self-link="">\[INFRA]
</dt><dd>Anne van Kesteren; Domenic Denicola. <a href="https://infra.spec.whatwg.org/"><cite>Infra Standard</cite></a>. Living Standard. URL: <a href="https://infra.spec.whatwg.org/">https://infra.spec.whatwg.org/</a>
</dd><dt id="biblio-url" data-no-self-link="">\[URL]
</dt><dd><a href="https://url.spec.whatwg.org/"><cite>URL Standard</cite></a>. Living Standard. URL: <a href="https://url.spec.whatwg.org/">https://url.spec.whatwg.org/</a>
</dd><dt id="biblio-webidl" data-no-self-link="">\[WEBIDL]
</dt><dd>Edgar Chen; Timothy Gu. <a href="https://webidl.spec.whatwg.org/"><cite>Web IDL Standard</cite></a>. Living Standard. URL: <a href="https://webidl.spec.whatwg.org/">https://webidl.spec.whatwg.org/</a>
</dd></dl>
<h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3>
<dl>
<dt id="biblio-base64" data-no-self-link="">\[BASE64]
</dt><dd><a href="https://www.ietf.org/rfc/rfc4648.txt"><cite>The Base16, Base32, and Base64 Data Encodings</cite></a>. Standards Track. URL: <a href="https://www.ietf.org/rfc/rfc4648.txt">https://www.ietf.org/rfc/rfc4648.txt</a>
</dd><dt id="biblio-ecma-262" data-no-self-link="">\[ECMA-262]
</dt><dd><a href="https://tc39.es/ecma262/"><cite>ECMAScript® Language Specification</cite></a>. Standards Track. URL: <a href="https://tc39.es/ecma262/">https://tc39.es/ecma262/</a>
</dd><dt id="biblio-evalsourceurl" data-no-self-link="">\[EvalSourceURL]
</dt><dd><a href="https://web.archive.org/web/20120814122523/http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/"><cite>Give your eval a name with //@ sourceURL</cite></a>. archive. URL: <a href="https://web.archive.org/web/20120814122523/http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/">https://web.archive.org/web/20120814122523/http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/</a>
</dd><dt id="biblio-v2format" data-no-self-link="">\[V2Format]
</dt><dd><a href="https://docs.google.com/document/d/1xi12LrcqjqIHTtZzrzZKmQ3lbTv9mKrN076UB-j3UZQ/edit?hl=en_US"><cite>Source Map Revision 2 Proposal</cite></a>. URL: <a href="https://docs.google.com/document/d/1xi12LrcqjqIHTtZzrzZKmQ3lbTv9mKrN076UB-j3UZQ/edit?hl=en_US">https://docs.google.com/document/d/1xi12LrcqjqIHTtZzrzZKmQ3lbTv9mKrN076UB-j3UZQ/edit?hl=en_US</a>
</dd><dt id="biblio-vlq" data-no-self-link="">\[VLQ]
</dt><dd><a href="https://en.wikipedia.org/wiki/Variable-length_quantity"><cite>Variable-length quantity</cite></a>. reference article. URL: <a href="https://en.wikipedia.org/wiki/Variable-length_quantity">https://en.wikipedia.org/wiki/Variable-length_quantity</a>
</dd><dt id="biblio-wasmnamesbinaryformat" data-no-self-link="">\[WasmNamesBinaryFormat]
</dt><dd><a href="https://www.w3.org/TR/wasm-core-2/#names%E2%91%A2"><cite>WebAssembly Names binary format</cite></a>. Living Standard. URL: <a href="https://www.w3.org/TR/wasm-core-2/#names%E2%91%A2">https://www.w3.org/TR/wasm-core-2/#names%E2%91%A2</a>
</dd></dl>
</div>
Terms and definitions {#terminology}
====================================
For the purposes of this document, the following terms and definitions apply.
: <dfn>Generated Code</dfn>
:: The code which is generated by the compiler or transpiler.
: <dfn>Original Source</dfn>
:: The source code which has not been passed through the compiler.
: <dfn>Base64 VLQ</dfn> [[VLQ]]
:: A [[base64]] value, where the most significant bit (the 6th bit) is used as the continuation bit,
and the "digits" are encoded into the string least significant first, and where the least
significant bit of the first digit is used as the sign bit.
Note: The values that can be represented by the VLQ Base64 encoded are limited to
32-bit quantities until some use case for larger values is presented. This
means that values exceeding 32-bits are invalid and implementations may reject
them. The sign bit is counted towards the limit, but the continuation bits are not.
<div class="example">
The string `"iB"` represents a [=Base64 VLQ=] with two digits. The first digit
`"i"` encodes the bit pattern `0x100010`, which has a continuation bit of `1` (the
VLQ continues), a sign bit of `0` (non-negative), and the value bits `0x0001`.
The second digit `B` encodes the bit pattern `0x000001`, which has a continuation
bit of `0`, no sign bit, and value bits `0x00001`. The decoding of this VLQ string
is the number 17.
</div>
<div class="example">
The string `"V"` represents a [=Base64 VLQ=] with one digit. The digit
`"V"` encodes the bit pattern `0x010101`, which has a continuation bit of `0`
(no continuation), a sign bit of `1` (negative), and the value bits `0x1010`.
The decoding of this VLQ string is the number -10.
</div>
: <dfn>Source Mapping URL</dfn>
:: The URL referencing the location of a source map from the [=Generated code=].
: <dfn>Column</dfn>
:: The zero-based indexed offset within a line of the generated code. How this offset is
measured can depend on the content type. For JavaScript and CSS based source
maps, they are defined to be in UTF-16 code units analogous to JavaScript string indices. That means
that "A" (`LATIN CAPITAL LETTER A`) measures as 1 code unit, and "🔥" (`FIRE`) measures as 2 code
units. For WebAssembly, columns are defined as byte offsets from the beginning of the binary
content (and there is only one group representing a line). Source maps for other content types
may diverge from this.
Source Map Format {#source-map-format}
======================================
A source map is a JSON document containing a top-level JSON object with the
following structure:
```json
{
"version" : 3,
"file": "out.js",
"sourceRoot": "",
"sources": ["foo.js", "bar.js"],
"sourcesContent": [null, null],
"names": ["src", "maps", "are", "fun"],
"mappings": "A,AAAB;;ABCDE"
"ignoreList": [0]
}
```
* <dfn for="json"><code>version</code></dfn> is the version field which must always be the number
`3` as an integer. The source map may be rejected if the field has any other value.
* <dfn for="json"><code>file</code></dfn> is an optional name of the generated code
that this source map is associated with. It's not specified if this can
be a URL, relative path name, or just a base name. Source map generators may
choose the appropriate interpretation for their contexts of use.
* <dfn for="json"><code>sourceRoot</code></dfn> is an optional source root string,
used for relocating source files on a server or removing repeated values in
the [=json/sources=] entry. This value is prepended to the individual entries in the
[=json/sources=] field.
* <dfn for="json"><code>sources</code></dfn> is a list of original sources
used by the [=json/mappings=] entry. Each entry is either a string that is a
(potentially relative) URL or `null` if the source name is not known.
* <dfn for="json"><code>sourcesContent</code></dfn> is an optional list
of source content (i.e., the [=Original Source=]) strings, used when the source
cannot be hosted. The contents are listed in the same order as the [=json/sources=].
Entries may be `null` if some original sources should be retrieved by name.
* <dfn for="json"><code>names</code></dfn> is an optional list of symbol names which may be used by the [=json/mappings=] entry.
* <dfn for="json"><code>mappings</code></dfn> is a string with the encoded mapping data (see [[#mappings-structure]]).
* <dfn for="json"><code>ignoreList</code></dfn> is an optional list of indices of files that
should be considered third party code, such as framework code or bundler-generated code. This
allows developer tools to avoid code that developers likely don't want to see
or step through, without requiring developers to configure this beforehand.
It refers to the [=json/sources=] array and lists the indices of all the known third-party sources
in the source map. Some browsers may also use the deprecated <code>x_google_ignoreList</code>
field if <code>[=json/ignoreList=]</code> is not present.
A <dfn export>decoded source map</dfn> is a [=struct=] with the following fields:
<dl dfn-for="decoded source map">
<dt><dfn>file</dfn></dt>
<dd>A [=string=] or null.</dd>
<dt><dfn>sources</dfn></dt>
<dd>A [=list=] of [=decoded source|decoded sources=].</dd>
<dt><dfn>mappings</dfn></dt>
<dd>A [=list=] of [=decoded mapping|decoded mappings=].</dd>
</dl>
A <dfn>decoded source</dfn> is a [=struct=] with the following fields:
<dl dfn-for="decoded source">
<dt><dfn>URL</dfn></dt>
<dd>A [=/URL=] or null.</dd>
<dt><dfn>content</dfn></dt>
<dd>A [=string=] or null.</dd>
<dt><dfn>ignored</dfn></dt>
<dd>A [=boolean=].</dd>
</dl>
To <dfn export>decode a source map from a JSON string</dfn> |str| given a [=/URL=] |baseURL|, run the
following steps:
1. Let |jsonMap| be the result of [=parse a JSON string to an Infra value|parsing a JSON string to
an Infra value=] |str|.
1. If |jsonMap| is not a [=/map=], report an error and abort these steps.
1. [=Decode a source map=] given |jsonMap| and |baseURL|, and return its result if any.
To <dfn export>decode a source map</dfn> given a [=string=]-keyed [=/map=] |jsonMap| and a [=/URL=]
|baseURL|, run the following steps:
1. If |jsonMap|[`"version"`] does not [=map/exist=] or |jsonMap|[`"version"`] is not 3,
[=optionally report an error=].
1. If |jsonMap|[`"mappings"`] does not [=map/exist=] or |jsonMap|[`"mappings"`], is not a
[=string=], throw an error.
1. If |jsonMap|[`"sources"`] does not [=map/exist=] or |jsonMap|[`"sources"`], is not a
[=list=], throw an error.
1. Let |sourceMap| be a new [=decoded source map=].
1. Set |sourceMap|'s [=decoded source map/file=] to [=optionally get a string=] `"file"` from |jsonMap|.
1. Set |sourceMap|'s [=decoded source map/sources=] to the result of [=decode source map
sources|decoding source map sources=] given |baseURL| with:
- [=decode source map sources/sourceRoot=] set to [=optionally get a string=] `"sourceRoot"`
from |jsonMap|;
- [=decode source map sources/sources=] set to [=optionally get a list of optional strings=]
`"sources"` from |jsonMap|;
- [=decode source map sources/sourcesContent=] set to [=optionally get a list of optional
strings=] `"sourcesContent"` from |jsonMap|;
- [=decode source map sources/ignoredSources=] set to [=optionally get a list of array indexes=]
`"ignoreList"` from |jsonMap|.
1. Set |sourceMap|'s [=decoded source map/mappings=] to the result of [=decode source map
mappings|decoding source map mappings=] with:
- [=decode source map mappings/mappings=] set to |jsonMap|[`"mappings"`];
- [=decode source map mappings/names=] set to [=optionally get a list of strings=] `"names"`
from |jsonMap|;
- [=decode source map mappings/sources=] set to |sourceMap|'s [=decoded source map/sources=].
1. Return |sourceMap|.
To <dfn>optionally get a string</dfn> |key| from a [=string=]-keyed [=/map=] |jsonMap|, run the
following steps:
1. If |jsonMap|[|key|] does not [=map/exist=], return null.
1. If |jsonMap|[|key|] is not a [=string=], [=optionally report an error=] and return null.
1. Return |jsonMap|[|key|].
To <dfn>optionally get a list of strings</dfn> |key| from a [=string=]-keyed [=/map=]
|jsonMap|, run the following steps:
1. If |jsonMap|[|key|] does not [=map/exist=], return a new empty [=list=].
1. If |jsonMap|[|key|] is not a [=list=], [=optionally report an error=] and return a new empty
[=list=].
1. Let |list| be a new empty [=list=].
1. [=For each=] |jsonItem| of |jsonMap|[|key|]:
1. If |jsonItem| is a [=string=], [=list/append=] it to |list|.
<!-- TODO: What happens in this case? -->
1. Else, [=optionally report an error=] and append `""` to |list|.
1. Return |list|.
To <dfn>optionally get a list of optional strings</dfn> |key| from a [=string=]-keyed [=/map=]
|jsonMap|, run the following steps:
1. If |jsonMap|[|key|] does not [=map/exist=], return a new empty [=list=].
1. If |jsonMap|[|key|] is not a [=list=], [=optionally report an error=] and return a new empty
[=list=].
1. Let |list| be a new empty [=list=].
1. [=For each=] |jsonItem| of |jsonMap|[|key|]:
1. If |jsonItem| is a [=string=], [=list/append=] it to |list|.
1. Else,
1. If |jsonItem| is not null, [=optionally report an error=].
1. Append null to |list|.
1. Return |list|.
To <dfn>optionally get a list of array indexes</dfn> |key| from a [=string=]-keyed [=/map=]
|jsonMap|, run the following steps:
1. If |jsonMap|[|key|] does not [=map/exist=], return a new empty [=list=].
1. If |jsonMap|[|key|] is not a [=list=], [=optionally report an error=] and return a new empty
[=list=].
1. Let |list| be a new empty [=list=].
1. [=For each=] |jsonItem| of |jsonMap|[|key|]:
1. If |jsonItem| is a non-negative integer number, [=list/append=] it to |list|.
1. Else,
<!-- Test case: a floating point number and a negative number -->
1. If |jsonItem| is not null, [=optionally report an error=].
1. Append null to |list|.
1. Return |list|.
To <dfn>optionally report an error</dfn>, implementations can choose to:
- Do nothing.
- Report an error to the user, and continue processing.
- Throw an error to abort the running algorithm. ([[Infra#algorithm-control-flow]])
Mappings Structure {#mappings-structure}
----------------------------------------
The [=json/mappings=] data is broken down as follows:
- each group representing a line in the generated file is separated by a semicolon (`;`)
- each segment is separated by a comma (`,`)
- each segment is made up of 1, 4, or 5 variable length fields.
The fields in each segment are:
1. The zero-based starting [=column=] of the line in the generated code that the segment represents.
If this is the first field of the first segment, or the first segment following a new generated
line (`;`), then this field holds the whole [=Base64 VLQ=]. Otherwise, this field contains
a [=Base64 VLQ=] that is relative to the previous occurrence of this field. <em>Note that this
is different from the subsequent fields below because the previous value is reset after every generated line.</em>
2. If present, the zero-based index into the [=json/sources=] list. This field contains a [=Base64 VLQ=]
relative to the previous occurrence of this field, unless it is the first occurrence of this
field, in which case the whole value is represented.
3. If present, the zero-based starting line in the original source. This field contains a
[=Base64 VLQ=] relative to the previous occurrence of this field, unless it is the first
occurrence of this field, in which case the whole value is represented. Must be present if there
is a source field.
4. If present, the zero-based starting [=column=] of the line in the original source. This
field contains a [=Base64 VLQ=] relative to the previous occurrence of this field, unless it
is the first occurrence of this field, in which case the whole value is represented. Must
be present if there is a source field.
5. If present, the zero-based index into the [=json/names=] list associated with this segment. This
field contains a [=Base64 VLQ=] relative to the previous occurrence of this field, unless it
is the first occurrence of this field, in which case the whole value is represented.
Note: The purpose of this encoding is to reduce the source map size. VLQ encoding reduced source maps by 50% relative to the [[V2Format]] in tests performed
using Google Calendar.
Note: Segments with one field are intended to represent generated code that is unmapped because there
is no corresponding original source code, such as code that is generated by a compiler. Segments
with four fields represent mapped code where a corresponding name does not exist. Segments with five
fields represent mapped code that also has a mapped name.
Note: Using file offsets was considered but rejected in favor of using line/column data to avoid becoming
misaligned with the original due to platform-specific line endings.
A <dfn>decoded mapping</dfn> is a [=struct=] with the following fields:
<dl dfn-for="decoded mapping">
<dt><dfn>generatedLine</dfn></dt>
<dd>A non-negative integer.</dd>
<dt><dfn>generatedColumn</dfn></dt>
<dd>A non-negative integer.</dd>
<dt><dfn>originalSource</dfn></dt>
<dd>A [=decoded source=] or null.</dd>
<dt><dfn>originalLine</dfn></dt>
<dd>A non-negative integer or null.</dd>
<dt><dfn>originalColumn</dfn></dt>
<dd>A non-negative integer or null.</dd>
<dt><dfn>name</dfn></dt>
<dd>A [=string=] or null.</dd>
</dl>
To <dfn>decode source map mappings</dfn> given a [=string=]
<dfn for="decode source map mappings">|mappings|</dfn>, a [=list=] of [=strings=]
<dfn for="decode source map mappings">|names|</dfn>, and a [=list=] of [=decoded source|decoded
sources=] <dfn for="decode source map mappings">|sources|</dfn>, run the following steps:
1. [=Validate base64 VLQ groupings=] with |mappings|.
1. Let |decodedMappings| be a new empty [=list=].
1. Let |groups| be the result of [=strictly split|strictly splitting=] |mappings| on `;`.
1. Let |generatedLine| be 0.
1. Let |originalLine| be 0.
1. Let |originalColumn| be 0.
1. Let |sourceIndex| be 0.
1. Let |nameIndex| be 0.
1. While |generatedLine| is less than |groups|'s [=list/size=]:
1. If |groups|[|generatedLine|] is not the empty string, then:
1. Let |segments| be the result of [=strictly split|strictly splitting=]
|groups|[|generatedLine|] on `,`.
1. Let |generatedColumn| be 0.
1. [=For each=] |segment| in |segments|:
1. Let |position| be a [=position variable=] for |segment|, initially pointing at
|segment|'s start.
1. [=Decode a base64 VLQ=] from |segment| given |position| and let
|relativeGeneratedColumn| be the result.
1. If |relativeGeneratedColumn| is null, [=optionally report an error=] and continue
with the next iteration.
1. Increase |generatedColumn| by |relativeGeneratedColumn|. If the result is negative,
[=optionally report an error=] and continue with the next iteration.
1. Let |decodedMapping| be a new [=decoded mapping=] whose
[=decoded mapping/generatedLine=] is |generatedLine|,
[=decoded mapping/generatedColumn=] is |generatedColumn|,
[=decoded mapping/originalSource=] is null,
[=decoded mapping/originalLine=] is null,
[=decoded mapping/originalColumn=] is null,
and [=decoded mapping/name=] is null.
1. Append |decodedMapping| to |decodedMappings|.
1. [=Decode a base64 VLQ=] from |segment| given |position| and let |relativeSourceIndex|
be the result.
1. [=Decode a base64 VLQ=] from |segment| given |position| and let
|relativeOriginalLine| be the result.
1. [=Decode a base64 VLQ=] from |segment| given |position| and let
|relativeOriginalColumn| be the result.
1. If |relativeOriginalColumn| is null, then:
1. If |relativeSourceIndex| is not null, [=optionally report an error=].
1. Continue with the next iteration.
1. Increase |sourceIndex| by |relativeSourceIndex|.
1. Increase |originalLine| by |relativeOriginalLine|.
1. Increase |originalColumn| by |relativeOriginalColumn|.
1. If any of |sourceIndex|, |originalLine|, or |originalColumn| are less than 0, or if
|sourceIndex| is greater than or equal to |sources|'s [=list/size=], [=optionally
report an error=].
1. Else,
1. Set |decodedMapping|'s [=decoded mapping/originalSource=] to
|sources|[|sourceIndex|].
1. Set |decodedMapping|'s [=decoded mapping/originalLine=] to |originalLine|.
1. Set |decodedMapping|'s [=decoded mapping/originalColumn=] to |originalColumn|.
1. [=Decode a base64 VLQ=] from |segment| given |position| and let |relativeNameIndex|
be the result.
1. If |relativeNameIndex| is not null, then:
1. Increase |nameIndex| by |relativeNameIndex|.
1. If |nameIndex| is negative or greater than |names|'s [=list/size=], [=optionally
report an error=].
1. Else, set |decodedMapping|'s [=decoded mapping/name=] to |names|[|nameIndex|].
1. If |position| does not point to the end of |segment|, [=optionally report an
error=].
1. Increase |generatedLine| by 1.
1. Return |decodedMappings|.
To <dfn>validate base64 VLQ groupings</dfn> from a [=string=] |groupings|, run the following steps:
1. If |groupings| is not an [=ASCII string=], throw an error.
1. If |groupings| contains any [=code unit=] other than:
- U+002C (,) or U+003B (;);
- U+0030 (0) to U+0039 (9);
- U+0041 (A) to U+005A (Z);
- U+0061 (a) to U+007A (z);
- U+002B (+), U+002F (/)
NOTE: These are the valid [[base64]] characters (excluding the padding character `=`), together
with `,` and `;`.
then throw an error.
To <dfn>decode a base64 VLQ</dfn> from a [=string=] |segment| given a [=position variable=]
|position|, run the following steps:
1. If |position| points to the end of |segment|, return null.
1. Let |first| be a [=byte=] whose the [=byte/value=] is the number corresponding to |segment|'s
|position|th [=code unit=], according to the [[base64]] encoding.
NOTE: The two most significant bits of |first| are 0.
1. Let |sign| be 1 if |first| & 0x01 is 0x00, and -1 otherwise.
1. Let |value| be (|first| >> 1) & 0x0F, as a number.
1. Let |nextShift| be 16.
1. Let |currentByte| be |first|.
1. While |currentByte| & 0x20 is 0x20:
1. Advance |position| by 1.
1. If |position| points to the end of |segment|, throw an error.
1. Set |currentByte| to the [=byte=] whose the [=byte/value=] is the number corresponding to
|segment|'s |position|th [=code unit=], according to the [[base64]] encoding.
1. Let |chunk| be |currentByte| & 0x1F, as a number.
1. Add |chunk| * |nextShift| to |value|.
1. If |value| is greater than or equal to 2<sup>31</sup>, throw an error.
1. Multiply |nextShift| by 32.
1. Advance |position| by 1.
1. If |value| is 0 and |sign| is -1, return -2147483648.
NOTE: -2147483648 is the smallest 32-bit signed integer.
1. Return |value| * |sign|.
NOTE: In addition to returning the decoded value, this algorithm updates the [=position variable=]
in the calling algorithm.
### [=decoded mapping|Mappings=] for generated JavaScript code ### {#mappings-javascript}
Generated code positions that may have [=decoded mapping|mapping=] entries are defined in terms of *input elements*
as per [=ECMAScript Lexical Grammar=]. [=decoded mapping|Mapping=] entries must point to either:
1. the first code point of the source text matched by
[=IdentifierName=], [=PrivateIdentifier=], [=Punctuator=], [=DivPunctuator=], [=RightBracePunctuator=],
[=NumericLiteral=] and [=RegularExpressionLiteral=].
1. any code point of the source text matched by
[=Comment=], [=HashbangComment=], [=StringLiteral=], [=Template=],
[=TemplateSubstitutionTail=], [=WhiteSpace=] and [=LineTerminator=].
### [=decoded mapping/Names=] for generated JavaScript code
Source map generators should create a [=decoded mapping|mapping=] entry with a
[=decoded mapping/name=] field for a JavaScript token, if
1. The original source language construct maps semantically to the generated
JavaScript code.
1. The original source language construct has a name.
Then the [=decoded mapping/name=] of the [=decoded mapping|mapping=] entry should be
the name of the original source language construct. A [=decoded mapping|mapping=] with
a non-null [=decoded mapping/name=] is called a <dfn>named mapping</dfn>.
Example: A minifier renaming functions and variables or removing function names
from immediately invoked function expressions.
The following enumeration lists productions of the ECMAScript [=Syntactic Grammar=]
and the respective token or non-terminal (on the right-hand side of the production)
for which source map generators should emit a [=named mapping=].
The [=decoded mapping|mapping=] entry created for such tokens must follow [[#mappings-javascript]].
The enumeration should be understood as the "minimum". In general,
source map generators are free to emit any additional [=named mappings=].
Note: The enumeration also lists tokens where generators "may" emit named [=decoded mapping|mappings=] in addition
to the tokens where they "should". These reflect the reality where existing tooling emits or
expects [=named mappings=]. The duplicated [=named mapping=] is comparably cheap: Indices into
[=json/names=] are encoded relative to each other so subsequent mappings to the same name are
encoded as 0 (`A`).
1. The [=BindingIdentifier=](s) for [=LexicalDeclaration=], [=VariableStatement=]
and [=Parameter List=].
1. The [=BindingIdentifier=] for [=FunctionDeclaration=], [=FunctionExpression=],
[=AsyncFunctionDeclaration=], [=AsyncFunctionExpression=], [=GeneratorDeclaration=],
[=GeneratorExpression=], [=AsyncGeneratorDeclaration=], and [=AsyncGeneratorExpression=] if it
exists, or the opening parenthesis `(` preceding the [=FormalParameters=] otherwise.
Source map generators may chose to emit a [=named mapping=] on the opening parenthesis regardless of
the presence of the [=BindingIdentifier=].
1. For an [=ArrowFunction=] or [=AsyncArrowFunction=]:
1. The `=>` token where [=ArrowFunction=] is produced with a single [=BindingIdentifier=] for
[=ArrowParameters=]. Or [=AsyncArrowFunction=] is produced with an [=AsyncArrowBindingIdentifier=].
Note: This describes the case of (async) arrow functions with a single parameter, where
that single parameter is not wrapped in parenthesis.
1. The opening parenthesis `(` where [=ArrowFunction=] or [=AsyncArrowFunction=] is produced
with [=ArrowFormalParameters=].
Source map generators may chose to additionally emit a named [=decoded mapping|mapping=]
on the `=>` token for consistency with (1).
1. The [=ClassElementName=] for [=MethodDefinition=]. This includes generators, async
methods, async generators and accessors. For [=MethodDefinition=] where
[=ClassElementName=] is "constructor", the [=decoded mapping/name=] should be the original
class name if applicable.
Source map generators may chose to additionally emit a named [=decoded mapping|mapping=] on the opening parenthesis `(`.
1. Source map generators may emit named [=decoded mapping|mappings=] for [=IdentifierReference=] in [=Expression=].
Resolving Sources {#resolving-sources}
--------------------------------------
If the sources are not absolute URLs after prepending the [=json/sourceRoot=], the sources are
resolved relative to the SourceMap (like resolving the script `src` attribute in an HTML document).
To <dfn>decode source map sources</dfn> given a [=/URL=] |baseURL|,
a [=string=] or null <dfn for="decode source map sources">|sourceRoot|</dfn>,
a [=list=] of either [=strings=] or nulls <dfn for="decode source map sources">|sources|</dfn>,
a [=list=] of either [=strings=] or nulls <dfn for="decode source map sources">|sourcesContent|</dfn>,
and a [=list=] of numbers <dfn for="decode source map sources">|ignoredSources|</dfn>,
run the following steps:
1. Let |decodedSources| be a new empty [=list=].
1. Let |sourceURLPrefix| be "".
1. If |sourceRoot| is not null, then:
1. If |sourceRoot| contains the code point U+002F (/), then:
1. Let |index| be the index of the last occurrence of U+002F (/) in |sourceRoot|.
1. Set |sourceURLPrefix| to the [=code unit substring|substring=] of |sourceRoot| from 0 to
|index| + 1.
1. Else, set |sourceURLPrefix| to the concatenation of |sourceRoot| and "/".
1. [=For each=] |source| of |sources| with index |index|:
1. Let |decodedSource| be a new [=decoded source=] whose [=decoded source/URL=] is null,
[=decoded source/content=] is null, and [=decoded source/ignored=] is false.
1. If |source| is not null:
1. Set |source| to the [=string/concatenate|concatenation=] of |sourceURLPrefix| and |source|.
1. Let |sourceURL| be the result of [=URL parser|URL parsing=] |source| with |baseURL|.
1. If |sourceURL| is failure, [=optionally report an error=].
1. Else, set |decodedSource|'s [=decoded source/URL=] to |sourceURL|.
1. If |index| is in |ignoredSources|, set |decodedSource|'s [=decoded source/ignored=] to true.
1. If |sourcesContent|'s [=list/size=] is greater than or equal to |index|, set
|decodedSource|'s [=decoded source/content=] to |sourcesContent|[|index|].
1. [=list/Append=] |decodedSource| to |decodedSources|.
1. Return |decodedSources|.
NOTE: Implementations that support showing source contents but do not support showing multiple
sources with the same URL and different content will arbitrarily choose one of the various contents
corresponding to the given URL.
Extensions {#extensions}
------------------------
Source map consumers must ignore any additional unrecognized properties, rather than causing the
source map to be rejected, so that additional features can be added to this format without
breaking existing users.
Index Map {#index-map}
======================
To support concatenating generated code and other common post-processing,
an alternate representation of a map is supported:
```json
{
"version" : 3,
"file": "app.js",
"sections": [
{
"offset": {"line": 0, "column": 0},
"map": {
"version" : 3,
"file": "section.js",
"sources": ["foo.js", "bar.js"],
"names": ["src", "maps", "are", "fun"],
"mappings": "AAAA,E;;ABCDE"
}
},
{
"offset": {"line": 100, "column": 10},
"map": {
"version" : 3,
"file": "another_section.js",
"sources": ["more.js"],
"names": ["more", "is", "better"],
"mappings": "AAAA,E;AACA,C;ABCDE"
}
}
]
}
```
The index map follows the form of the standard map. Like the regular source map,
the file format is JSON with a top-level object. It shares the [=json/version=] and
[=json/file=] field from the regular source map, but gains a new [=index-map/sections=] field.
<dfn dfn-for="index-map"><code>sections</code></dfn> is an array of [=index-map/Section=] objects.
## Section ## {#section-object}
Section objects have the following fields:
* <dfn dfn-for="index-map"><code>offset</code></dfn> is an object with two fields, `line` and `column`,
that represent the offset into generated code that the referenced source map
represents.
* <dfn dfn-for="index-map"><code>map</code></dfn> is an embedded complete source map object.
An embedded map does not inherit any values from the containing index map.
The sections must be sorted by starting position and the represented sections
must not overlap.
Retrieving Source Maps {#linking-and-fetching}
========================================================
Linking generated code to source maps {#linking-generated-code}
---------------------------------------------------------------
While the source map format is intended to be language and platform agnostic, it is useful
to define how to reference to them for the expected use-case of web server-hosted JavaScript.
There are two possible ways to link source maps to the output. The first requires server
support in order to add an HTTP header and the second requires an annotation in the source.
Source maps are linked through URLs as defined in [[URL]]; in particular,
characters outside the set permitted to appear in URIs must be percent-encoded
and it may be a data URI. Using a data URI along with [=json/sourcesContent=] allows
for a completely self-contained source map.
The HTTP `sourcemap` header has precedence over a source annotation, and if both are present,
the header URL should be used to resolve the source map file.
Regardless of the method used to retrieve the [=Source Mapping URL=] the same
process is used to resolve it, which is as follows:
When the [=Source Mapping URL=] is not absolute, then it is relative to the generated code's
<dfn>source origin</dfn>. The [=source origin=] is determined by one of the following cases:
- If the generated source is not associated with a script element that has a `src`
attribute and there exists a `//# sourceURL` comment in the generated code, that
comment should be used to determine the [=source origin=].
Note: Previously, this was
`//@ sourceURL`, as with `//@ sourceMappingURL`, it is reasonable to accept both
but `//#` is preferred.
- If the generated code is associated with a script element and the script element has
a `src` attribute, the `src` attribute of the script element will be the [=source origin=].
- If the generated code is associated with a script element and the script element does
not have a `src` attribute, then the [=source origin=] will be the page's origin.
- If the generated code is being evaluated as a string with the `eval()` function or
via `new Function()`, then the [=source origin=] will be the page's origin.
### Linking through HTTP headers ### {#linking-http-header}
If a file is served through HTTP(S) with a `sourcemap` header, the value of the header is
the URL of the linked source map.
```
sourcemap: <url>
```
Note: Previous revisions of this document recommended a header name of `x-sourcemap`. This
is now deprecated; `sourcemap` is now expected.
### Linking through inline annotations ### {#linking-inline}
The generated code should include a comment, or the equivalent construct depending on its
language or format, named `sourceMappingURL` and that contains the URL of the source map. This
specification defines how the comment should look like for JavaScript, CSS, and WebAssembly.
Other languages should follow a similar convention.
For a given language there can be multiple ways of detecting the `sourceMappingURL` comment,
to allow for different implementations to choose what is less complex for them. The generated
code <dfn>unambiguously links to a source map</dfn> if the result of all the extraction methods
is the same.
If a tool consumes one or more source files that [=unambiguously links to a source map=] and it
produces an output file that links to a source map, it must do so [=unambiguously links to a
source map|unambiguously=].
<div class="example">
The following JavaScript code links to a source map, but it does not do so [=unambiguously links
to a source map|unambiguously=]:
```js
let a = `
//# sourceMappingURL=foo.js.map
//`;
```
Extracing a Source Map URL from it [=extract a Source Map URL from JavaScript through
parsing|through parsing=] gives null, while [=extract a Source Map URL from JavaScript
without parsing|without parsing=] gives `foo.js.map`.
</div>
<div class="issue">
Having multiple ways to extract a source map URL, that can lead to different
results, can have negative security and privacy implications. Implementations
that need to detect which source maps are potentially going to be loaded are
strongly encouraged to always apply both algorithms, rather than just assuming
that they will give the same result.
A fix to this problem is being worked on, and will likely involve early returning
from the below algorithms whenever there is a comment (or comment-like) that
contains the characters U+0060 (`), U+0022 ("), or U+0027 ('), or the the
sequence U+002A U+002F (*/).
</div>
#### Extraction methods for JavaScript sources #### {#extraction-javascript}
To <dfn export>extract a Source Map URL from JavaScript through parsing</dfn> a [=string=] |source|,
run the following steps:
1. Let |tokens| be the [=list=] of [=tokens=]
obtained by parsing |source| according to [[ECMA-262]].
1. [=For each=] |token| in |tokens|, in reverse order:
1. If |token| is not a [=single-line comment=] or a [=multi-line comment=], return null.
1. Let |comment| be the content of |token|.
1. If [=match a Source Map URL in a comment|matching a Source Map URL in=]
|comment| returns a [=string=], return it.
1. Return null.
To <dfn export>extract a Source Map URL from JavaScript without parsing</dfn> a [=string=] |source|,
run the following steps:
1. Let |lines| be the result of [=strictly split|strictly splitting=] |source| on [=line
terminator code points|ECMAScript line terminator code points=].
1. Let |lastURL| be null.
1. [=For each=] |line| in |lines|:
1. Let |position| be a [=position variable=] for |line|, initially pointing at the start of |line|.
1. [=While=] |position| doesn't point past the end of |line|:
1. [=Collect a sequence of code points=] that are [=white space code points|ECMAScript
white space code points=] from |line| given |position|.
NOTE: The collected code points are not used, but |position| is still updated.
1. If |position| points past the end of |line|, [=break=].
1. Let |first| be the [=code point=] of |line| at |position|.
1. Increment |position| by 1.
1. If |first| is U+002F (/) and |position| does not point past the end of |line|, then:
1. Let |second| be the [=code point=] of |line| at |position|.
1. Increment |position| by 1.
1. If |second| is U+002F (/), then:
1. Let |comment| be the [=code point substring=] from |position| to the end of |line|.
1. If [=match a Source Map URL in a comment|matching a Source Map URL in=]
|comment| returns a [=string=], set |lastURL| to it.
1. [=Break=].
1. Else if |second| is U+002A (*), then:
1. Let |comment| be the empty [=string=].
1. While |position| + 1 doesn't point past the end of |line|:
1. Let |c1| be the [=code point=] of |line| at |position|.
1. Increment |position| by 1.
1. Let |c2| be the [=code point=] of |line| at |position|.
1. If |c1| is U+002A (*) and |c2| is U+002F (/), then:
1. If [=match a Source Map URL in a comment|matching a Source Map URL in=]
|comment| returns a [=string=], set |lastURL| to it.
1. Increment |position| by 1.
1. Append |c1| to |comment|.
1. Else, set |lastURL| to null.
1. Else, set |lastURL| to null.
Note: We reset |lastURL| to null whenever we find a non-comment code character.
1. Return |lastURL|.