From 5131971794828d3cc8ff78e044cb5fd7216ea5f0 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Thu, 6 Apr 2023 13:25:30 +0200 Subject: [PATCH 1/9] Initial infrastructure for writing the spec --- .gitignore | 2 ++ Makefile | 12 ++++++++++++ source-map.bs | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 source-map.bs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ffe59d8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.venv +source-map.html diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f35cc8a --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +.PHONY: all +all: build + +.PHONY: build +build: .venv + .venv/bin/bikeshed spec + +.venv: + python3 -mvenv .venv + .venv/bin/pip install --upgrade pip + .venv/bin/pip install bikeshed + .venv/bin/bikeshed update diff --git a/source-map.bs b/source-map.bs new file mode 100644 index 0000000..889bff1 --- /dev/null +++ b/source-map.bs @@ -0,0 +1,23 @@ +
+Title: Source Map
+H1: Source Map
+Shortname: source-map
+Level: 1
+Status: LS
+URL: https://source-map.github.io/source-map-rfc/
+Editor: TBD
+Repository: source-map/source-map-rfc
+Abstract: A specification for mapping transpiled source code to back to the original sources.
+
+ + + +Hello World From de9d8fc00a2b427eac635d5214ed0fbe4aea3dec Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Thu, 6 Apr 2023 14:39:33 +0200 Subject: [PATCH 2/9] Add source map spec as bikeshed --- Makefile | 4 + source-map.bs | 313 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 315 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f35cc8a..512ca13 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,10 @@ all: build build: .venv .venv/bin/bikeshed spec +.PHONY: watch +watch: .venv + .venv/bin/bikeshed watch + .venv: python3 -mvenv .venv .venv/bin/pip install --upgrade pip diff --git a/source-map.bs b/source-map.bs index 889bff1..c3bb4eb 100644 --- a/source-map.bs +++ b/source-map.bs @@ -7,7 +7,7 @@ Status: LS URL: https://source-map.github.io/source-map-rfc/ Editor: TBD Repository: source-map/source-map-rfc -Abstract: A specification for mapping transpiled source code to back to the original sources. +Abstract: A specification for mapping transpiled source code (primarily JavaScript) back to the original sources. This specification is a living document and describes a hardened version of the Source Map v3 specification. -Hello World +
+{
+  "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"
+  }
+}
+
+ +Background {#background} +======================== + +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 the source maps expanded the verbosity of the format started to +be become a problem. The v2 was created trading some simplicity and flexibility +to reduce to 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 podivilov. + +This document codifies the prior art that is Source Map v3 but is more specific +about the precise meanings of the specification. + +Terminology {#terminology} +========================== + +Generated Code is the code which is generated +by the compiler or transpiler. + +Original Source is the source code which has not +been passed through the compiler. + +Base 64 VLQ refers to the [[VLQ]] is 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. + +Source Mapping URL refers to the URL referencing +the location of a source map from the generated code. + +Column is the 0 (zero) indexed offsets within a line of the +generated code measured in UTF-16 offsets. + +Source Map Format {#source-map-format} +====================================== + +The 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;" +} +``` + +Note: Previous specification suggested an order to the keys in this file, but +for practical reasons the order cannot be defined in many JSON generators and +has never been enforced. + +version is the version field. The +original specification referred to this as "file version field" but it has been +used in practice to version the source map specification. Today it's only valid +value is `3` and refers to this specification of the source map. + +file 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 and as such has mostly informal +character. + +sourceRoot an optional source root, +useful for relocating source files on a server or removing repeated values in +the "sources" entry. This value is prepended to the individual entries in the +"source" field. + +sources is a list of original sources +used by the "mappings" entry. Each entry is either a string that is a +(potentially relative) URL or `null` if the source name is not known. + +sourcesContent an optional list +of source content (that is the [=Original Source=]), useful when the "source" +can't be hosted. The contents are listed in the same order as the [=sources=]. +`null` may be used if some original sources should be retrieved by name. + +names a list of symbol names used by the [=mappings=] entry. + +mappings a string with the encoded mapping data (see [[#mappings-structure]]). + +Mappings Structure {#mappings-structure} +---------------------------------------- + +The [=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. Note that this + is different than the fields below because the previous value is reset after every generated line. + +2. If present, an zero-based index into the [=sources=] list. This field is a [[base64]] [[VLQ]] + relative to the previous occurrence of this field, unless this 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 represented. This field is a + [[base64]] [[VLQ]] relative to the previous occurrence of this field, unless this is the first + occurrence of this field, in which case the whole value is represented. Always present if there + is a source field. + +4. If present, the zero-based starting [=column=] of the line in the source represented. This + field is a [[base64]] [[VLQ]] relative to the previous occurrence of this field, unless this + is the first occurrence of this field, in which case the whole value is represented. Always + present if there is a source field. + +5. If present, the zero-based index into the [=names=] list associated with this segment. This + field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the + first occurrence of this field, in which case the whole value is represented. + +Resolving Sources {#resolving-sources} +-------------------------------------- + +If the sources are not absolute URLs after prepending of the [=sourceRoot=], the sources are +resolved relative to the SourceMap (like resolving script src in a html document). + +Encoding {#encoding} +-------------------- + +For simplicity, the character set encoding is always UTF-8. + +Compression {#compression} +-------------------------- + +The file is allowed to be GZIP compressed. It is not expected that in-browser consumers of +the the source map will support GZIP compression directly but that they will consume an +uncompressed map that may be GZIP'd for transport. + +Note: the support of compression is unclear and some tools also support Brotli. This part +of the specification should be consired for hardening. + +Extensions {#extensions} +------------------------ + +Additional fields may be added to the top level source map provided the fields begin with the +`x_` naming convention. It is expected that the extensions would be classified by the +organization providing the extension, such as `x_google_linecount`. Field names outside +the `x_` namespace are reserved for future revisions. It is recommended that fields be +namespaced by domain, i.e. `x_com_google_gwt_linecount`. + +Note: HTTP no longer recommends `x-` prefixes, the future of `x_` prefixes in this specification +should be reconsidered. + +Known Extensions +---------------- + +x_google_linecount The number of lines represented by this source map. + +x_google_ignoreList Identifies third-party sources (such as framework +code or bundler-generated code), allowing developers to avoid code that they don't want to see +or step through, without having to configure this beforehand. + +It refers to the [=sources=] array, and lists the indices of all the known third-party sources +in that source map. When parsing the source map, developer tools can use this to determine +sections of the code that the browser loads and runs that could be automatically ignore-listed. + +Index Map +========= + +TODO: add index map + +Conventions {#conventions} +========================== + +Source Map Naming {#source-map-naming} +-------------------------------------- + +Optionally, a source map will have the same name as the generated file but with a `.map` +extension. For example, for `page.js` a source map named `page.js.map` would be generated. + +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 have a some conventions for the expected use-case of web server hosted javascript. + +There are two suggested ways to link source maps to the output. The first requires server +support to add a HTTP header and the second requires an annotation in the source. + +The HTTP header should supply the source map URL reference as: + +``` +SourceMap: +``` + +Note: previous revisions of this document recommended a header name of `X-SourceMap`. This +is now deprecated; `SourceMap` is now expected. + +The generated code should include a line at the end of the source, with the following form: + +``` +//# sourceMappingURL= +``` + +Note: The prefix for this annotation was initially `//@` however this conflicts with Internet +Explorer's Conditional Compilation and was changed to `//#`. It is reasonable for tools to +also accept `//@` but `//#` is preferred. + +This recommendation works well for JavaScript, it is expected that other source files will +have other conventions. + +<url> is a URL as defined in [[URL]]; in particular, +characters outside the set permitted to appear in URIs must be percent-encoded +and it maybe a data URI. Using a data URI along with [=sourcesContent=] allow +for a completely self-contained source-map. + +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 +source origin. 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 eval’d code to named generate code +------------------------------------------ + +There is an existing convention that should be supported for the use of source maps with +eval'd code, it has the following form: + +``` +//# sourceURL=foo.js +``` + +It is described in [[EvalSourceURL]]. + +Language Neutral Stack Mapping Notes +==================================== + +Stack tracing mapping without knowledge of the source language is not covered by this document. + +Multi-level Mapping Notes +========================= + +It is getting more common to have tools generate source from some DSL (templates) or to compile +TypeScript -> JavaScript -> minified JavaScript, resulting in multiple translations before the +final source map is created. This problem can be handled in one of two ways. The easy but +lossy way is to ignore the intermediate steps in the process for the purposes of debugging, +the source location information from the translation is either ignored (the intermediate +translation is considered the “Original Source”) or the source location information is carried +through (the intermediate translation hidden). The more complete way is to support multiple +levels of mapping: if the Original Source also has a source map reference, the user is given +the choice of using the that as well. + +However, It is unclear what a "source map reference" looks like in anything other than JavaScript. +More specifically, what a source map reference looks like in a language that doesn't support +JavaScript style single line comments. + +JSON over HTTP Transport +======================== + +For historic security reasons, when delivering source maps over HTTP, servers may prepend a +line starting with the string `)]}'` to the source map. If the response starts with this +string clients must ignore the first line. From b9e3c9d3eaa56ceff60b0fb4ad2ffef0cf82658d Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Thu, 6 Apr 2023 15:12:13 +0200 Subject: [PATCH 3/9] Document indexed source maps --- source-map.bs | 181 +++++++++++++++++++++++++++++++------------------- 1 file changed, 113 insertions(+), 68 deletions(-) diff --git a/source-map.bs b/source-map.bs index c3bb4eb..7391139 100644 --- a/source-map.bs +++ b/source-map.bs @@ -12,11 +12,11 @@ Abstract: A specification for mapping transpiled source code (primarily JavaScri @@ -25,27 +25,27 @@ spec:bikeshed-1; type:dfn; for:railroad; text:optional "VLQ": { "href": "https://en.wikipedia.org/wiki/Variable-length_quantity", "title": "Variable-length quantity", - "publisher": "Wikipedia", - "status": "reference article" + "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" + "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" + "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" + "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" } } @@ -74,7 +74,7 @@ by the compiler or transpiler. Original Source is the source code which has not been passed through the compiler. -Base 64 VLQ refers to the [[VLQ]] is a [[base64]] value, +Base64 VLQ refers to the [[VLQ]] is 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. @@ -83,7 +83,7 @@ Note: The values that can be represented by the VLQ Base64 encoded are limited t 32 bit quantities until some use case for larger values is presented. Source Mapping URL refers to the URL referencing -the location of a source map from the generated code. +the location of a source map from the [=Generated code=]. Column is the 0 (zero) indexed offsets within a line of the generated code measured in UTF-16 offsets. @@ -96,13 +96,13 @@ 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;" + "version" : 3, + "file": "out.js", + "sourceRoot": "", + "sources": ["foo.js", "bar.js"], + "sourcesContent": [null, null], + "names": ["src", "maps", "are", "fun"], + "mappings": "A,AAAB;;ABCDE;" } ``` @@ -149,29 +149,29 @@ The [=mappings=] data is broken down as follows: 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. Note that this - is different than the fields below because the previous value is reset after every generated line. +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. Note that this + is different than the fields below because the previous value is reset after every generated line. -2. If present, an zero-based index into the [=sources=] list. This field is a [[base64]] [[VLQ]] - relative to the previous occurrence of this field, unless this is the first occurrence of this - field, in which case the whole value is represented. +2. If present, an zero-based index into the [=sources=] list. This field is a [=Base64 VLQ=] + relative to the previous occurrence of this field, unless this 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 represented. This field is a - [[base64]] [[VLQ]] relative to the previous occurrence of this field, unless this is the first - occurrence of this field, in which case the whole value is represented. Always present if there - is a source field. + [=Base64 VLQ=] relative to the previous occurrence of this field, unless this is the first + occurrence of this field, in which case the whole value is represented. Always present if there + is a source field. 4. If present, the zero-based starting [=column=] of the line in the source represented. This - field is a [[base64]] [[VLQ]] relative to the previous occurrence of this field, unless this - is the first occurrence of this field, in which case the whole value is represented. Always - present if there is a source field. + field is a [=Base64 VLQ=] relative to the previous occurrence of this field, unless this + is the first occurrence of this field, in which case the whole value is represented. Always + present if there is a source field. 5. If present, the zero-based index into the [=names=] list associated with this segment. This - field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the - first occurrence of this field, in which case the whole value is represented. + field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the + first occurrence of this field, in which case the whole value is represented. Resolving Sources {#resolving-sources} -------------------------------------- @@ -198,20 +198,17 @@ Extensions {#extensions} ------------------------ Additional fields may be added to the top level source map provided the fields begin with the -`x_` naming convention. It is expected that the extensions would be classified by the -organization providing the extension, such as `x_google_linecount`. Field names outside -the `x_` namespace are reserved for future revisions. It is recommended that fields be -namespaced by domain, i.e. `x_com_google_gwt_linecount`. - -Note: HTTP no longer recommends `x-` prefixes, the future of `x_` prefixes in this specification -should be reconsidered. +x_ naming convention. It is expected that the extensions would be classified by the +organization providing the extension, such as x_google_linecount. Field names outside +the x_ namespace are reserved for future revisions. It is recommended that fields be +namespaced by domain, i.e. x_com_google_gwt_linecount. Known Extensions ---------------- -x_google_linecount The number of lines represented by this source map. +x_google_linecount The number of lines represented by this source map. -x_google_ignoreList Identifies third-party sources (such as framework +x_google_ignoreList Identifies third-party sources (such as framework code or bundler-generated code), allowing developers to avoid code that they don't want to see or step through, without having to configure this beforehand. @@ -222,11 +219,59 @@ sections of the code that the browser loads and runs that could be automatically Index Map ========= -TODO: add 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}, "url": "url_for_part1.map"} + { + "offset": {"line": 100, "column": 10}, + "map": { + "version" : 3, + "file": "section.js", + "sources": ["foo.js", "bar.js"], + "names": ["src", "maps", "are", "fun"], + "mappings": "AAAA,E;;ABCDE;" + } + } + ], +} +``` + +The index map follow the form of the standard map. Like the regular source map +the file format is JSON with a top-level object. It shares the [=version=] and +[=file=] field from the regular source map, but gains a new [=sections=] field. + +sections is an array of JSON objects that itself has two +fields [=offset=] and a source map reference. + +## Section + +offset is an object with two fields, line +and column, that represent the offset into generated code that the +referenced source map represents. + +url is an entry that must be a [[URL]] where a source +map can be found for this section and the [=url=] is resolved in the same way as +the [=sources=] fields in the standard map. + +map is an alternative entry to [=url=] that must be 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 +may not overlap and each section must either use [=map=] or [=url=] but not mboth. Conventions {#conventions} ========================== +The following conventions should be followed when working with source maps or +when generating them. + Source Map Naming {#source-map-naming} -------------------------------------- @@ -269,29 +314,29 @@ characters outside the set permitted to appear in URIs must be percent-encoded and it maybe a data URI. Using a data URI along with [=sourcesContent=] allow for a completely self-contained source-map. -Regardless of the method used to retrieve the source mapping URL the same process is used to -resolve it, which is as follows: +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 -source origin. The source origin is determined by one of the following cases: +When the [=Source Mapping URL=] is not absolute, then it is relative to the generated code's +source origin. 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. + 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. + 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. + 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. + via `new Function()`, then the [=source origin=] will be the page's origin. -Linking eval’d code to named generate code ------------------------------------------- +Linking eval'd code to named generated code +------------------------------------------- There is an existing convention that should be supported for the use of source maps with eval'd code, it has the following form: From 07c5e6de2b9a46344bb56bae769ccacdd3ca8ef2 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Thu, 6 Apr 2023 15:14:17 +0200 Subject: [PATCH 4/9] Added editors --- source-map.bs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source-map.bs b/source-map.bs index 7391139..e715a45 100644 --- a/source-map.bs +++ b/source-map.bs @@ -5,7 +5,10 @@ Shortname: source-map Level: 1 Status: LS URL: https://source-map.github.io/source-map-rfc/ -Editor: TBD +Editor: John Lenz, Google +Editor: Victor Porof, Google +Editor: Nick Fitzgerald, Mozilla +Editor: Armin Ronacher, Sentry Repository: source-map/source-map-rfc Abstract: A specification for mapping transpiled source code (primarily JavaScript) back to the original sources. This specification is a living document and describes a hardened version of the Source Map v3 specification. From 477903c8f9426f538facff0da533be93f4043f7d Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Thu, 6 Apr 2023 15:16:25 +0200 Subject: [PATCH 5/9] Separate between editors and former editors --- source-map.bs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source-map.bs b/source-map.bs index e715a45..01b6b19 100644 --- a/source-map.bs +++ b/source-map.bs @@ -5,10 +5,11 @@ Shortname: source-map Level: 1 Status: LS URL: https://source-map.github.io/source-map-rfc/ -Editor: John Lenz, Google -Editor: Victor Porof, Google -Editor: Nick Fitzgerald, Mozilla Editor: Armin Ronacher, Sentry +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-rfc Abstract: A specification for mapping transpiled source code (primarily JavaScript) back to the original sources. This specification is a living document and describes a hardened version of the Source Map v3 specification. From c4fed3bc1e896481e8645145622e4efedc4e933a Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Thu, 6 Apr 2023 15:22:10 +0200 Subject: [PATCH 6/9] Properly reference Pavel Podivilov --- source-map.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source-map.bs b/source-map.bs index 01b6b19..e451a83 100644 --- a/source-map.bs +++ b/source-map.bs @@ -64,7 +64,7 @@ projects using the source maps expanded the verbosity of the format started to be become a problem. The v2 was created trading some simplicity and flexibility to reduce to 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 podivilov. +The v3 format is based on suggestions made by Pavel Podivilov (Google). This document codifies the prior art that is Source Map v3 but is more specific about the precise meanings of the specification. From b13ee39f337210be62fdfc4da34af21a35c00d37 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Thu, 6 Apr 2023 15:24:59 +0200 Subject: [PATCH 7/9] Fix wording around Base64 VLQ --- source-map.bs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source-map.bs b/source-map.bs index e451a83..0de69dc 100644 --- a/source-map.bs +++ b/source-map.bs @@ -78,10 +78,10 @@ by the compiler or transpiler. Original Source is the source code which has not been passed through the compiler. -Base64 VLQ refers to the [[VLQ]] is 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. +Base64 VLQ: [[VLQ]] is 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. From 6fbaeacd648095e77a275e7939e56a0cbb18b82b Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Thu, 6 Apr 2023 15:29:45 +0200 Subject: [PATCH 8/9] Fix some markdown issues --- source-map.bs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/source-map.bs b/source-map.bs index 0de69dc..66f7dfc 100644 --- a/source-map.bs +++ b/source-map.bs @@ -12,6 +12,7 @@ Former Editor: Nick Fitzgerald, Mozilla Previous Version: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# Repository: source-map/source-map-rfc Abstract: A specification for mapping transpiled source code (primarily JavaScript) back to the original sources. This specification is a living document and describes a hardened version of the Source Map v3 specification. +Markup Shorthands: markdown yes +Note: **Spec Editorial Modification:** the sections "license" and "discussion" +were remove from the regular text. + Background {#background} ======================== @@ -62,13 +70,14 @@ 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 the source maps expanded the verbosity of the format started to -be become a problem. The v2 was created trading some simplicity and flexibility -to reduce to 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). +be become a problem. The v2 ([[V2Format]]) was created trading some simplicity +and flexibility to reduce to 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). -This document codifies the prior art that is Source Map v3 but is more specific -about the precise meanings of the specification. +This document codifies the prior art that is Source Map v3 but is more specific +about the precise meanings of the specification. Terminology {#terminology} ========================== @@ -90,8 +99,17 @@ Note: The values that can be represented by the VLQ Base64 encoded are limited t Source Mapping URL refers to the URL referencing the location of a source map from the [=Generated code=]. -Column is the 0 (zero) indexed offsets within a line of the -generated code measured in UTF-16 offsets. +Column is the 0 (zero) indexed offsets within a line of the +generated code measured in UTF-16 offsets. + +General Goals {#general-goals} +============================== + +The goals for the v3 format of Source Maps + +* Reduce the overall size to improve parse time, memory consumption, and download time. +* Support source level debugging allowing bidirectional mapping +* Support server side stack trace deobfuscation Source Map Format {#source-map-format} ====================================== @@ -115,15 +133,15 @@ Note: Previous specification suggested an order to the keys in this file, but for practical reasons the order cannot be defined in many JSON generators and has never been enforced. -version is the version field. The +version is the version field. The original specification referred to this as "file version field" but it has been -used in practice to version the source map specification. Today it's only valid -value is `3` and refers to this specification of the source map. +used in practice to version the source map specification. `3` refers to this +specification of the source map. file 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 and as such has mostly informal -character. +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 and as such has mostly informal +character. sourceRoot an optional source root, useful for relocating source files on a server or removing repeated values in @@ -157,8 +175,8 @@ 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. Note that this - is different than the fields below because the previous value is reset after every generated line. + a [=Base64 VLQ=] that is relative to the previous occurrence of this field. _Note that this + is different than the fields below because the previous value is reset after every generated line._ 2. If present, an zero-based index into the [=sources=] list. This field is a [=Base64 VLQ=] relative to the previous occurrence of this field, unless this is the first occurrence of this @@ -178,6 +196,9 @@ The fields in each segment are: field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. +Note: This encoding reduces the source map size 50% relative to the V2 format in tests performed using +Google Calendar. + Resolving Sources {#resolving-sources} -------------------------------------- @@ -196,9 +217,6 @@ The file is allowed to be GZIP compressed. It is not expected that in-browser the the source map will support GZIP compression directly but that they will consume an uncompressed map that may be GZIP'd for transport. -Note: the support of compression is unclear and some tools also support Brotli. This part -of the specification should be consired for hardening. - Extensions {#extensions} ------------------------ @@ -221,6 +239,12 @@ It refers to the [=sources=] array, and lists the indices of all the known third in that source map. When parsing the source map, developer tools can use this to determine sections of the code that the browser loads and runs that could be automatically ignore-listed. +Notes on File Offsets +--------------------- + +Using file offsets were considered but rejected in favor of using line/column data to avoid becoming +misaligned with the original due to platform specific line endings. + Index Map ========= @@ -377,6 +401,6 @@ JavaScript style single line comments. JSON over HTTP Transport ======================== -For historic security reasons, when delivering source maps over HTTP, servers may prepend a +For historic security reasons, when delivering source maps over HTTP, servers may prepend a line starting with the string `)]}'` to the source map. If the response starts with this -string clients must ignore the first line. +string clients must ignore the first line.