ドラフト ECMA-426 / 2026年3月14日

ソースマップ形式仕様

この仕様について

https://tc39.es/ecma426/ の文書は、最も正確かつ最新のソースマップ仕様です。最新の公開スナップショットの内容に加え、次のスナップショットに含まれる変更も反映されています。

この仕様への貢献

この仕様はGitHub上で開発されています。仕様の開発には以下の方法で貢献できます:

この文書の作成方法について詳しくは コロフォン を参照してください。

はじめに

本Ecma規格は、トランスパイルされたソースコードを元のソースへマッピングするためのソースマップ形式を定義します。

ソースマップ形式の目標は以下の通りです:

オリジナルソースマップ形式(v1)は、Closure Inspectorで最適化されたJavaScriptコードのソースレベルのデバッグを可能にするためにJoseph Schorrによって作成されました(この形式自体は言語非依存です)。しかし、ソースマップを利用するプロジェクトの規模が拡大するにつれて、フォーマットの冗長性が問題となり始めました。v2形式(Source Map Revision 2 Proposal)は、いくらかの単純さと柔軟性を犠牲にフォーマット全体のサイズを削減するために作成されました。v2による変更を踏まえても、ソースマップファイルサイズが有用性を制限していました。v3形式は、Pavel Podivilov (Google) の提案に基づいています。

ソースマップ形式はもはやバージョン番号を持たず、常に "3" と固定されています。

2023~2024年にかけて、ソースマップ形式はより正確なEcma規格へと発展し、多くの人々の大きな貢献がありました。さらなるソースマップ形式の改良はTC39-TG4からも期待されています。

Asumu Takikawa、Nicolò Ribaudo、Jon Kuperman
ECMA-426 第1版 プロジェクト編集者

1 適用範囲

本規格は、JavaScript、WebAssembly、CSSへとコンパイルされたコードのデバッグ体験を向上させるために、様々な開発ツールが使用するソースマップ形式を定義します。

2 適合性

適合するソースマップ文書は、本仕様で詳述された構造に準拠したJSON文書です。

適合するソースマップ生成器は、適合するソースマップ文書を生成し、その生成物が本仕様のアルゴリズムで(オプションのものも含めて)エラーの報告なしにデコードできるようにするべきです。

適合するソースマップ消費者は、ソースマップ文書の取得(該当する場合)、およびデコードのために、本仕様で規定されたアルゴリズムを実装する必要があります。適合する消費者は、仕様がアルゴリズムにオプションでエラーを報告できることを示している場合には、エラーを無視したり、終了せずに報告することが許されます。

3 参考文献

以下の文書は本文中で参照されており、その内容の一部または全体が本書の要求事項となる場合があります。発行日付きの参照については記載された版のみが適用されます。発行日なしの参照については、参照文書の最新の版(および修正版等)が適用されます。

3.1 標準文献

ECMA-262, ECMAScript® 言語仕様.
https://tc39.es/ecma262/

ECMA-404, JSONデータ交換形式.
https://www.ecma-international.org/publications-and-standards/standards/ecma-404/

3.2 参考文献(情報提供)

IETF RFC 4648, Base16, Base32, Base64 データエンコーディング.
https://datatracker.ietf.org/doc/html/rfc4648

WebAssembly コア仕様.
https://www.w3.org/TR/wasm-core-2/

WHATWG Encoding.
https://encoding.spec.whatwg.org/

WHATWG Fetch.
https://fetch.spec.whatwg.org/

WHATWG Infra.
https://infra.spec.whatwg.org/

WHATWG URL.
https://url.spec.whatwg.org/

4 表記規約

この仕様は ECMA-262(表記規約) で定義される表記規約に従い、本節で示す拡張を含みます。

4.1 アルゴリズム規約

4.1.1 暗黙の完了

この仕様で宣言されるすべての 抽象操作 は、アルゴリズムで宣言された戻り型を含む、正常完了またはthrow完了を返すものと暗黙的にみなされます。例えば、次のような抽象操作は:

4.1.1.1 GetTheAnswer ( input )

抽象操作GetTheAnswerは引数input整数)を受け取り、整数を返します。

これは以下と同等です:

4.1.1.2 GetTheAnswer2 ( input )

抽象操作GetTheAnswer2は引数input整数)を受け取り、正常完了を含む整数、またはthrow完了のいずれかを返します。

すべての 抽象操作 への呼び出しで 完了レコード を返すものは、 明示的に Completion 呼び出しでラップされていない限り、 ReturnIfAbrupt マクロで暗黙的にラップされていると見なされます。例えば:

  1. resultGetTheAnswer(value) とする。
  2. secondCompletion(GetTheAnswer(value)) とする。

これは次と等価です:

  1. result を ReturnIfAbrupt(GetTheAnswer(value)) とする。
  2. secondCompletion(GetTheAnswer(value)) とする。

4.1.2 オプションエラー

アルゴリズムがオプションでエラーを報告する場合、実装は次のいずれかの挙動が選択できます:

  • アルゴリズムの残りを継続して実行する。
  • (たとえばブラウザコンソールで)ユーザーにエラーを報告し、アルゴリズムの残りを継続して実行する。
  • ThrowCompletionを返す。

実装はオプションエラーごとに異なる挙動を選択できます。

4.2 文法表記

この仕様はECMA-262(文法表記)で定義される文法表記慣習に従い、以下に記す留意点があります:

  • 本仕様で定義される文法の終端記号は個々のコードポイントです。これはECMA-262の字句文法に類似し、ECMA-262の構文文法とは異なります。
  • 本仕様は文法パラメータ先読み制約を使用せず、文法定義の複雑さを低減しています。

5 用語と定義

この文書の目的では、以下の用語と定義が適用されます。

生成コード

コンパイラまたはトランスパイラによって生成されたコード。

オリジナルソース

コンパイラやトランスパイラを通していないソースコード。

ソースマップURL

URL生成コードからソースマップの場所を参照します。

カラム(column)

生成コードの行内で0始まりのインデックスを持つオフセット。JavaScriptとCSSのソースマップについてはUTF-16コード単位として、WebAssemblyソースマップについてはバイナリ内容(1行に表現)でのバイトインデックスとして算出します。

つまり"A"(LATIN CAPITAL LETTER A)は1コード単位、"🔥"(FIRE)は2コード単位で計測されます。他のコンテンツタイプのソースマップではこれと異なる場合があります。

6 base64 VLQ

base64 VLQbase64でエンコードされた可変長数量であり、最上位ビット(6ビット目)が継続ビットとして使われ、"数字"は文字列において下位から順にエンコードされ、最初の数字の最下位ビットが符号ビットとして使われます。

注1
base64 VLQエンコーディングで表現可能な値は、現時点では32ビット数量に制限されています(より大きな値の利用例が提示されるまで)。このため、32ビットを超える値は無効となり、実装はそれらを拒否する場合があります。符号ビットもこの制限に含まれますが、継続ビットは含みません。
注2
文字列"iB"は2つの数字からなるbase64 VLQを表します。最初の数字"i"はビットパターン0b100010をエンコードしており、これは継続ビットが1(VLQは継続)、符号ビットが0(非負)、値ビットが0b0001です。2つ目の数字Bはビットパターン0b000001をエンコードしており、継続ビットが0、符号ビットなし、値ビットが0b00001です。このVLQ文字列のデコード結果は数値17です。
注3
文字列"V"は1つの数字からなるbase64 VLQを表します。数字"V"はビットパターン0b010101をエンコードしており、継続ビットが0(継続なし)、符号ビットが1(負)、値ビットが0b1010です。このVLQ文字列のデコード結果は数値-10です。

base64 VLQは以下の字句文法に従います:

Vlq :: VlqDigitList VlqDigitList :: TerminalDigit ContinuationDigit VlqDigitList TerminalDigit :: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f ContinuationDigit :: g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /

6.1 VLQSignedValue

構文指示操作VLQSignedValueは引数を取らず、整数を返します。次の生成規則に対して分割定義されます:

Vlq :: VlqDigitList
  1. unsignedに、VLQUnsignedValueVlqDigitList)を代入する。
  2. もしunsigned modulo 2 = 1なら、signは-1とする。
  3. それ以外なら、signは1とする。
  4. valuefloor(unsigned / 2)を代入する。
  5. もしvalueが0かつsignが-1なら、-231を返す。
  6. もしvalueが231以上なら、エラーを投げる。
  7. sign × valueを返す。
ステップ6のチェックは、unsignedVLQUnsignedValueVlqDigitList)の値であり、Vlqの値でないため必要です。

6.2 VLQUnsignedValue

構文指示操作VLQUnsignedValueは引数を取らず非負の整数を返します。次の生成規則に対して分割定義されます:

Vlq :: VlqDigitList
  1. valueに、VLQUnsignedValueVlqDigitList)を代入する。
  2. もしvalueが232以上なら、エラーを投げる。
  3. valueを返す。
VlqDigitList :: ContinuationDigit VlqDigitList
  1. leftVLQUnsignedValueContinuationDigit のもの)を設定する。
  2. rightVLQUnsignedValueVlqDigitList のもの)を設定する。
  3. left + right × 25 を返す。
TerminalDigit :: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f
  1. この生成規則によりマッチされた文字をdigitとする。
  2. 整数であるdigitに対応する値を、IETF RFC 4648で定義されるbase64エンコーディングに従いvalueとする。
  3. アサートvalue < 32。
  4. valueを返す。
ContinuationDigit :: g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /
  1. この生成規則によりマッチされた文字をdigitとする。
  2. 整数であるdigitに対応する値を、IETF RFC 4648で定義されるbase64エンコーディングに従いvalueとする。
  3. アサート:32 ≤ value < 64。
  4. value - 32を返す。

7 JSON値ユーティリティ

この仕様のアルゴリズムはECMA-262の内部仕様上で定義されていますが、非JavaScriptプラットフォームでも簡単に実装できるよう設計されています。本節では、JSON値を扱うためのユーティリティを提供し、ECMA-262の詳細を抽象化します。

JSON値は、JSONオブジェクトJSON配列文字列数値真偽値、またはnullです。

JSONオブジェクトは、各プロパティについて:

JSON配列は、以下の条件を満たすJSONオブジェクトです:

7.1 ParseJSON ( string )

抽象操作ParseJSONは引数string(文字列)を受け取り、JSON値を返します。処理手順:

  1. resultCall(%JSON.parse%, null, « string » )を代入する。
  2. AssertresultJSON値であること。
  3. resultを返す。
編集者注
この抽象操作はECMA-262自体によって公開される予定です:tc39/ecma262#3540

7.2 JSONObjectGet ( object, key )

抽象操作JSONObjectGetはobjectJSONオブジェクト)とkey(文字列)を受け取り、JSON値またはmissingを返します。指定したkeyに対応する値を返します。手順:

  1. もしobjectkeyの独自プロパティを持たない場合、missingを返す。
  2. propobjectkeyの独自プロパティを代入する。
  3. prop[[Value]]属性を返す。

7.3 JSONArrayIterate ( array )

抽象操作JSONArrayIterateはarrayJSON配列)を受け取り、ListJSON値のリスト)を返します。「For each」による反復用に全ての要素が入ったListを返します。手順:

  1. lengthJSONObjectGet(array, "length")を設定する。
  2. アサートlengthは非負の整数値である。
  3. listに新しい空のListを設定する。
  4. iに0を設定する。
  5. i < (length) の間繰り返す:
    1. valueJSONObjectGet(array, ToString(𝔽(i)))を設定する。
    2. アサートvaluemissingでない。
    3. valuelistに追加する。
    4. ii+1に設定する。
  6. listを返す。

7.4 StringSplit ( string, separators )

抽象操作 StringSplit は、引数 string(文字列)と separators(空でない文字列の リスト)を受け取り、文字列の リストを返します。 この操作は、separators の任意の要素で区切られた部分文字列に string を分割します。 複数のセパレーターが一致する場合、separators 内で先に現れるものが優先されます。 この操作が呼び出された時、以下の手順を実行します:

  1. partsに新しい空のリストを設定する。
  2. strLenstringの長さを設定する。
  3. lastStartに0を設定する。
  4. iに0を設定する。
  5. i < strLen の間繰り返す:
    1. matchedfalseを設定する。
    2. separatorsの各String sepについて:
      1. sepLensepの長さを設定する。
      2. candidateに、substring(string, i, min(i + sepLen, strLen)) を設定する。
      3. もしcandidatesep かつ matchedfalseなら:
        1. chunksubstring(string, lastStart, i) を設定する。
        2. chunkpartsに追加する。
        3. lastStarti + sepLenを設定する。
        4. ii + sepLenを設定する。
        5. matchedtrueを設定する。
    3. もしmatchedfalseなら、ii + 1を設定する。
  6. chunksubstring(string, lastStart, strLen) を設定する。
  7. chunkpartsに追加する。
  8. partsを返す。

8 位置型

8.1 位置レコード

位置レコードは、非負の行番号と非負のカラム番号からなるタプルです:

表1: 位置レコードのフィールド
フィールド名 値の型
[[Line]] 非負の整数型Number
[[Column]] 非負の整数型Number

8.2 元位置レコード

元位置レコードは、デコードソースレコード、非負の行、非負のカラム番号からなるタプルです。位置レコードに似ていますが、具体的なオリジナルソースファイル上のソース位置を記述します。

表2: 元位置レコードのフィールド
フィールド名 値の型
[[Source]] デコードソースレコード
[[Line]] 非負の整数型Number
[[Column]] 非負の整数型Number

8.3 ComparePositions ( first, second )

抽象操作 ComparePositions は、引数 firstPosition Record または Original Position Record)および secondPosition Record または Original Position Record)を取り、lesserequal、または greater を返す。これは firstsecond より前か等しいか後かに応じて、それぞれ lesserequalgreater を返す。Original Position Records[[Source]] フィールドは無視される。呼び出されたとき、次のステップを実行する:

  1. もしfirst.[[Line]] < second.[[Line]]であれば、lesserを返す。
  2. もしfirst.[[Line]] > second.[[Line]]であれば、greaterを返す。
  3. アサート: first.[[Line]]second.[[Line]]と等しい。
  4. もしfirst.[[Column]] < second.[[Column]]であれば、lesserを返す。
  5. もしfirst.[[Column]] > second.[[Column]]であれば、greaterを返す。
  6. equalを返す。

9 ソースマップ形式

ソースマップは、以下の構造をもつトップレベルのJSONオブジェクトを含む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]
}

9.1 ソースマップのデコード

デコード済みソースマップレコードは以下のフィールドを持ちます:

表3: デコード済みソースマップレコードのフィールド
フィールド名 値の型
[[File]] String または null
[[Sources]] Listデコード済みソースレコードの)
[[Mappings]] Listデコード済みマッピングレコードの)

デコード済みソースレコードは以下のフィールドを持ちます:

表4: デコード済みソースレコードのフィールド
フィールド名 値の型
[[URL]] URL または null
[[Content]] String または null
[[Ignored]] Boolean

9.1.1 ParseSourceMap ( string, baseURL )

抽象操作 ParseSourceMap は、引数 string(String 型)および baseURLURL)を取り、 Decoded Source Map Record を返す。呼び出されたとき、次のステップを実行する:

  1. jsonParseJSON(string) を設定する。
  2. jsonJSON オブジェクト でなければ、エラーをスローする。
  3. JSONObjectGet(json, "sections") が missing でなければ、
    1. DecodeIndexSourceMap(json, baseURL) を返す。
  4. DecodeSourceMap(json, baseURL) を返す。

9.1.2 DecodeSourceMap ( json, baseURL )

抽象操作 DecodeSourceMap は、引数 jsonJSON オブジェクト)および baseURLURL)を取り、 Decoded Source Map Record を返す。呼び出されたとき、次のステップを実行する:

  1. JSONObjectGet(json, "version") が 3𝔽 でなければ、オプションでエラーを報告してよい。
  2. mappingsFieldJSONObjectGet(json, "mappings") を設定する。
  3. mappingsFieldString でない場合、エラーをスローする。
  4. JSONObjectGet(json, "sources") が JSON 配列 でなければ、エラーをスローする。
  5. fileFieldGetOptionalString(json, "file") を設定する。
  6. sourceRootFieldGetOptionalString(json, "sourceRoot") を設定する。
  7. sourcesFieldGetOptionalListOfOptionalStrings(json, "sources") を設定する。
  8. sourcesContentFieldGetOptionalListOfOptionalStrings(json, "sourcesContent") を設定する。
  9. ignoreListFieldGetOptionalListOfArrayIndexes(json, "ignoreList") を設定する。
  10. sourcesDecodeSourceMapSources(baseURL, sourceRootField, sourcesField, sourcesContentField, ignoreListField) を設定する。
  11. namesFieldGetOptionalListOfStrings(json, "names") を設定する。
  12. mappingsDecodeMappings(mappingsField, namesField, sources) を設定する。
  13. mappings を昇順にソートする。Decoded Mapping Record aDecoded Mapping Record b より小さいのは、 ComparePositions(a.[[GeneratedPosition]], b.[[GeneratedPosition]]) が lesser の場合とする。
  14. Decoded Source Map Record { [[File]]: fileField, [[Sources]]: sources, [[Mappings]]: mappings } を返す。

9.1.2.1 GetOptionalString ( object, key )

抽象操作 GetOptionalString は、引数 objectJSON オブジェクト)と key(String 型)を取り、String または null を返す。呼び出されたとき、次のステップを実行する:

  1. valueJSONObjectGet(object, key) を設定する。
  2. valueString であればvalue を返す。
  3. valuemissing でなければ、オプションでエラーを報告してよい。
  4. null を返す。

9.1.2.2 GetOptionalListOfStrings ( object, key )

抽象操作 GetOptionalListOfStrings は、引数 objectJSON オブジェクト)および key(String 型)を取り、 List(String のリスト)を返す。呼び出されたとき、次のステップを実行する:

  1. list に新しい空の List を設定する。
  2. valuesJSONObjectGet(object, key) に設定する。
  3. valuesmissing であれば、list を返す。
  4. valuesJSON 配列 でなければ、
    1. オプションでエラーを報告してよい。
    2. list を返す。
  5. JSONArrayIterate(values) の各要素 item について、
    1. itemString であれば
      1. itemlist に追加する。
    2. それ以外の場合、
      1. オプションでエラーを報告してよい。
      2. ""list に追加する。
  6. list を返す。

9.1.2.3 GetOptionalListOfOptionalStrings ( object, key )

抽象操作 GetOptionalListOfOptionalStrings は、引数 objectJSON オブジェクト)と key(String 型)を取り、 List (String または null の List)を返す。呼び出されたとき、次のステップを実行する:

  1. list に新しい空の List を設定する。
  2. valuesJSONObjectGet(object, key) に設定する。
  3. valuesmissing であれば、list を返す。
  4. valuesJSON 配列 でなければ、
    1. オプションでエラーを報告してよい。
    2. list を返す。
  5. JSONArrayIterate(values) の各要素 item について、
    1. itemString であれば
      1. itemlist に追加する。
    2. それ以外の場合、
      1. itemnull であれば、オプションでエラーを報告してよい。
      2. nulllist に追加する。
  6. list を返す。

9.1.2.4 GetOptionalListOfArrayIndexes ( object, key )

抽象操作 GetOptionalListOfArrayIndexes は、引数 object(オブジェクト)と key(String 型)を取り、 非負の 整数Listを返す。 呼び出されたとき、次のステップを実行する:

  1. list を新しい空の リスト とする。
  2. valuesJSONObjectGet(object, key) とする。
  3. もし valuesmissing ならば、list を返す。
  4. もし valuesJSON配列 でなければ、次を行う:
    1. (オプションで)エラーを報告する
    2. list を返す。
  5. JSONArrayIterate(values) の各要素 item について、次を実行する:
    1. もし item整数の数値型 であり、 item+0𝔽 ならば:
      1. (item) を list に追加する。
    2. それ以外の場合:
      1. (オプションで)エラーを報告する
  6. list を返す。

9.2 マッピングの構造

mappings フィールド のデータは次のように分割される:

  • 生成ファイルの各行を表すグループはセミコロン(;)で区切られる
  • 各セグメントはカンマ(,)で区切られる
  • 各セグメントは 1, 4, または 5 個の可変長フィールドからなる

各セグメント内のフィールドは次の通り:

  1. このセグメントが表す生成コード の行の、0始まりの開始カラム。これが最初のセグメントの最初のフィールド、または新しい生成行(;)の直後の最初のセグメントの最初のフィールドの場合は、全体の base64 VLQ を格納する。それ以外の場合、このフィールドには前回のこのフィールドの値からの相対値を base64 VLQ で格納する。これは以下のフィールドとは異なり、前回値が行ごとにリセットされる点に注意。
  2. 存在する場合、sources リストへの 0 始まりのインデックス。このフィールドは前回のこのフィールドからの相対的な base64 VLQ となる。ただし最初の発生時は全体の値を格納する。
  3. 存在する場合、元のソース の 0 始まりの開始行。このフィールドは前回のこのフィールドからの相対の base64 VLQ となる。ただし最初の発生時は全体の値を格納する。source フィールドがある場合は必須。
  4. 存在する場合、元のソース の行の 0 始まりの開始 カラム。このフィールドは前回のこのフィールドからの相対の base64 VLQ となる。ただし最初の発生時は全体の値を格納する。source フィールドがある場合は必須。
  5. 存在する場合、このセグメントに関連付けられた names リストへの 0 始まりのインデックス。このフィールドは前回のこのフィールドからの相対の base64 VLQ となる。ただし最初の発生時は全体の値を格納する。
注 1
このエンコーディングの目的はソースマップのサイズを削減すること。VLQ エンコーディングによって、Google カレンダーでのテストではSource Map Revision 2 Proposal比で 50% 減少した。
注 2
1 フィールドのセグメントは、元のソース が存在しないため、対応する生成コードがマッピングされていないことを表す(例:コンパイラ生成コード)。4 フィールドのセグメントは対応する name が存在しないマッピング済みコードを表す。5 フィールドのセグメントはネームもマッピングされているコードを表す。
注 3
file のオフセットの使用も検討されたが、プラットフォーム固有の改行でずれが生じないよう、line/column データの使用が採用された。

Decoded Mapping Record には次のフィールドがある:

表 5: Decoded Mapping Record のフィールド
フィールド名 値の型
[[GeneratedPosition]] Position Record
[[OriginalPosition]] Original Position Record または null
[[Name]] String または null

9.2.1 マッピングの文法

MappingsField : LineList LineList : Line Line ; LineList Line : MappingListopt MappingList : Mapping Mapping , MappingList Mapping : GeneratedColumn GeneratedColumn OriginalSource OriginalLine OriginalColumn Nameopt GeneratedColumn : Vlq OriginalSource : Vlq OriginalLine : Vlq OriginalColumn : Vlq Name : Vlq

Decode Mapping State Record には次のフィールドがある:

表 6: Decode Mapping State Record のフィールド
フィールド名 値の型
[[GeneratedLine]] 非負の 整数
[[GeneratedColumn]] 非負の 整数
[[SourceIndex]] 非負の 整数
[[OriginalLine]] 非負の 整数
[[OriginalColumn]] 非負の 整数
[[NameIndex]] 非負の 整数

9.2.1.1 DecodeMappingsField

構文指示付き操作 DecodeMappingsField は、引数 stateDecode Mapping State Record)、mappingsリストDecoded Mapping Records)のリスト)、namesリスト(Stringのリスト))、sourcesリストDecoded Source Records のリスト))を取る。この操作は下記の生成規則ごとに分割して定義される。

LineList : Line ; LineList
  1. DecodeMappingsFieldLinestate, mappings, names, sources を引数として実行する。
  2. state.[[GeneratedLine]]state.[[GeneratedLine]] + 1 を設定する。
  3. state.[[GeneratedColumn]] に 0 を設定する。
  4. DecodeMappingsFieldLineListstate, mappings, names, sources を引数として実行する。
Line : [empty]
  1. 何もせず return する。
MappingList : Mapping , MappingList
  1. DecodeMappingsFieldMappingstate, mappings, names, sources を引数として実行する。
  2. DecodeMappingsFieldMappingListstate, mappings, names, sources を引数として実行する。
Mapping : GeneratedColumn
  1. DecodeMappingsFieldGeneratedColumnstate, mappings, names, sources を引数として実行する。
  2. もし state.[[GeneratedColumn]] < 0 ならば
    1. オプションでエラーを報告してよい。
    2. return する。
  3. position に新しい Position Record { [[Line]]: state.[[GeneratedLine]], [[Column]]: state.[[GeneratedColumn]] } を設定する。
  4. decodedMapping に新しい DecodedMappingRecord { [[GeneratedPosition]]: position, [[OriginalPosition]]: null, [[Name]]: null } を設定する。
  5. decodedMappingmappings に追加する。
Mapping : GeneratedColumn OriginalSource OriginalLine OriginalColumn Nameopt
  1. DecodeMappingsFieldGeneratedColumnstate, mappings, names, sources を引数として実行する。
  2. もし state.[[GeneratedColumn]] < 0 ならば
    1. オプションでエラーを報告してよい。
    2. return する。
  3. generatedPosition に新しい Position Record { [[Line]]: state.[[GeneratedLine]], [[Column]]: state.[[GeneratedColumn]] } を設定する。
  4. DecodeMappingsFieldOriginalSourcestate, mappings, names, sources を引数として実行する。
  5. DecodeMappingsFieldOriginalLinestate, mappings, names, sources を引数として実行する。
  6. DecodeMappingsFieldOriginalColumnstate, mappings, names, sources を引数として実行する。
  7. もし state.[[SourceIndex]] < 0 または state.[[SourceIndex]]sources の要素数 または state.[[OriginalLine]] < 0 または state.[[OriginalColumn]] < 0 ならば
    1. オプションでエラーを報告してよい。
    2. originalPositionnull を設定する。
  8. それ以外の場合、
    1. originalPosition に新しい Original Position Record { [[Source]]: sources[state.[[SourceIndex]]], [[Line]]: state.[[OriginalLine]], [[Column]]: state.[[OriginalColumn]] } を設定する。
  9. namenull を設定する。
  10. もし Name が存在する場合、
    1. DecodeMappingsFieldNamestate, mappings, names, sources を引数として実行する。
    2. もし state.[[NameIndex]] < 0 または state.[[NameIndex]]names の要素数であれば、オプションでエラーを報告してよい。
    3. それ以外の場合、namenames[state.[[NameIndex]]] を設定する。
  11. decodedMapping に新しい DecodedMappingRecord { [[GeneratedPosition]]: generatedPosition, [[OriginalPosition]]: originalPosition, [[Name]]: name } を設定する。
  12. decodedMappingmappings に追加する。
GeneratedColumn : Vlq
  1. relativeColumnVLQSignedValueVlq の値)を設定する。
  2. state.[[GeneratedColumn]]state.[[GeneratedColumn]] + relativeColumn を設定する。
OriginalSource : Vlq
  1. relativeSourceIndexVLQSignedValueVlq の値)を設定する。
  2. state.[[SourceIndex]]state.[[SourceIndex]] + relativeSourceIndex を設定する。
OriginalLine : Vlq
  1. relativeLineVLQSignedValueVlq の値)を設定する。
  2. state.[[OriginalLine]]state.[[OriginalLine]] + relativeLine を設定する。
OriginalColumn : Vlq
  1. relativeColumnVLQSignedValueVlq の値)を設定する。
  2. state.[[OriginalColumn]]state.[[OriginalColumn]] + relativeColumn を設定する。
Name : Vlq
  1. relativeNameVLQSignedValueVlq の値)を設定する。
  2. state.[[NameIndex]]state.[[NameIndex]] + relativeName を設定する。

9.2.2 DecodeMappings ( rawMappings, names, sources )

抽象操作 DecodeMappings は、引数 rawMappings(String 型)、namesString のリスト)、 sourcesリストDecoded Source Records))を取り、 Decoded Mapping Record のリストを返す。呼び出されたとき、次のステップを実行する:

  1. mappings に新しい空の リスト を設定する。
  2. mappingsNode に、rawMappingsMappingsFieldゴール記号としてパースしたときのルート Parse Node を設定する。
  3. パースに失敗した場合、
    1. オプションでエラーを報告してよい。
    2. mappings を返す。
  4. すべてのフィールドが 0 に設定された新しい Decode Mapping State Recordstate に設定する。
  5. DecodeMappingsFieldmappingsNodestate, mappings, names, sources を引数として実行する。
  6. mappings を返す。

9.2.3 生成されたJavaScriptコードのマッピング

生成コードの位置でmappingエントリーとなりうるものは、ECMAScript字句文法に則り、入力要素で定義されます。マッピングエントリは次のいずれかを指す必要があります:

  • IdentifierNamePrivateIdentifierPunctuatorDivPunctuatorRightBracePunctuatorNumericLiteralRegularExpressionLiteralで一致したソーステキストの最初のコードポイント。
  • CommentHashbangCommentStringLiteralTemplateTemplateSubstitutionTailWhiteSpaceLineTerminatorで一致したソーステキストのいずれかのコードポイント。

9.2.4 生成JavaScriptコードの名前

ソースマップ生成ツールは、次の場合、JavaScriptトークンについて[[Name]]フィールドを持つmappingエントリを生成するべきです:

  • 元ソースの言語構造が意味的に生成されたJavaScriptコードに対応する。
  • 元ソースの言語構造が名前を持つ。

その場合、mappingエントリの[[Name]]元ソース言語構造の名前となります。非nullな[[Name]]を持つmapping名前付きマッピングと呼ばれます。

注1
ミニファイアによる関数名や変数名の変更、即時実行関数式からの関数名の削除などのケース。

以下の列挙は、ECMAScript構文文法の生成規則と、その右辺のトークン・非終端で、ソースマップ生成ツールが名前付きマッピングを出力すべきものです。これらのトークンのために作成されるmappingエントリは、9.2.3に従います。

この列挙は「最低限」として扱います。一般に、ソースマップ生成ツールは追加の名前付きマッピングを自由に生成して構いません。

注2
この列挙には、生成ツールが「may(推奨)」として名前付きマッピングを出力するケースも含まれています。既存ツールが名前付きマッピングを出力・要求する現実を反映しています。重複した名前付きマッピングはほぼコストゼロです:namesへのインデックスは互いに相対で符号化されるので、同一名への連続したマッピングは0(A)として符号化されます。
  • LexicalDeclarationVariableStatementFormalParameterListに含まれるBindingIdentifier

  • FunctionDeclarationFunctionExpressionAsyncFunctionDeclarationAsyncFunctionExpressionGeneratorDeclarationGeneratorExpressionAsyncGeneratorDeclarationAsyncGeneratorExpressionに存在する場合はBindingIdentifier、存在しない場合はFormalParametersの直前の開き括弧(

    ソースマップ生成ツールはBindingIdentifierの有無に関わらず、開き括弧にも名前付きマッピングを出力してもよい。

  • ArrowFunctionまたはAsyncArrowFunctionの場合:

    • ArrowFunctionが単一BindingIdentifierArrowParametersとなる場合またはAsyncArrowFunctionAsyncArrowBindingIdentifierとなる場合の=>トークン。

      注3
      これは(async)アロー関数が単一パラメータかつ括弧で囲まれていないケースを指します。
    • ArrowFunctionまたはAsyncArrowFunctionArrowFormalParametersで生成される場合の開き括弧(

      ソースマップ生成ツールは前のケースとの一貫性のため、=>トークンにも追加で名前付きマッピングを出力しても良い。

  • MethodDefinitionClassElementName(ジェネレータ、asyncメソッド、asyncジェネレータ、アクセサ含む)。MethodDefinition内でClassElementName"constructor"なら[[Name]]は元のクラス名(該当する場合)とする。

    ソースマップ生成ツールは開き括弧(にも追加で名前付きマッピングを出力してもよい。

  • ソースマップ生成ツールはExpression内のIdentifierReferenceに対して名前付きマッピングを出力してもよい。

9.3 ソースの解決

sourceRootを前に付加した後でも、sourcesが絶対URLでない場合は、HTMLドキュメント内のscriptのsrc属性を解決するように、ソースマップを基準に相対的に解決されます。

9.3.1 DecodeSourceMapSources ( baseURL, sourceRoot, sources, sourcesContent, ignoreList )

抽象操作 DecodeSourceMapSources は、引数 baseURLURL)、 sourceRoot(String または null)、sourcesリスト。各要素は String または null)、 sourcesContentリスト。各要素は String または null)、 ignoreListリスト。各要素は0以上の整数) を受け取り、リスト(各要素は Decoded Source Record) を返す。呼び出されたとき、次の手順を行う:

  1. decodedSources を新しい空の リスト とする。
  2. sourcesContentCountsourcesContent の要素数とする。
  3. sourceUrlPrefix"" とする。
  4. もし sourceRootnull ならば、次を行う:
    1. もし sourceRoot がコードポイント U+002F(SOLIDUS)で終わる場合、
      1. sourceUrlPrefixsourceRoot を設定する。
    2. それ以外の場合:
      1. sourceUrlPrefixsourceRoot"/"連結結果を設定する。
  5. index を 0 とする。
  6. index < sources の長さ の間、繰り返す:
    1. sourcesources[index] とする。
    2. decodedSourceDecoded Source Record { [[URL]]: null, [[Content]]: null, [[Ignored]]: false  } とする。
    3. もし sourcenull ならば:
      1. sourcesourceUrlPrefixsource連結結果とする。
      2. sourceURLURL 解析 の結果(引数は source および baseURL)とする。
      3. もし sourceURLfailure ならば、(オプションで)エラーを報告する。
      4. それ以外の場合、decodedSource.[[URL]]sourceURL を設定する。
    4. もし ignoreListindex を含んでいれば、decodedSource.[[Ignored]]true を設定する。
    5. もし sourcesContentCount > index ならば、decodedSource.[[Content]]sourcesContent[index] を設定する。
    6. decodedSourcedecodedSources に追加する。
    7. indexindex + 1 を設定する。
  7. decodedSources を返す。
複数のURLを同じ値で異なる内容を持つ複数ソースの表示をサポートしていない実装は、URLごとにいずれかの内容を任意に選択することになります。

9.4 拡張

ソースマップ利用者は追加の認識されないプロパティを無視し、ソースマップの拒否につなげてはならず、このフォーマットが既存ユーザーを壊すことなく追加機能拡張できるようにすべきです。

10 インデックスソースマップ

生成コードの連結や他の一般的な後処理をサポートするため、ソースマップの別表現がサポートされています:

{
  "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"
      }
    }
  ]
}

インデックスマップは標準のマップと同じ形式に従います。通常のソースマップのように、ファイルフォーマットはJSONでトップレベルはオブジェクトです。通常のソースマップと同じくversionやfileフィールドを持ちますが、さらに新しいsectionsフィールドが追加されています。

sectionsフィールドは、以下のフィールドを持つオブジェクトの配列です:

sectionsは開始位置でソートされ、各sectionが表す部分は重なってはいけません。

10.1 DecodeIndexSourceMap ( json, baseURL )

抽象演算DecodeIndexSourceMapは、引数json(Object型)とbaseURLURL型)を受け取り、Decoded Source Map Recordを返します。呼び出し時に行う手順は次のとおりです:

  1. sectionsFieldJSONObjectGet(json, "sections") を設定する。
  2. アサート: sectionsFieldmissing ではない。
  3. sectionsFieldJSON 配列 でなければ、エラーをスローする。
  4. JSONObjectGet(json, "version") が 3𝔽 でなければ、オプションでエラーを報告してよい。
  5. fileFieldGetOptionalString(json, "file") を設定する。
  6. sourceMapDecoded Source Map Record { [[File]]: fileField, [[Sources]]: « », [[Mappings]]: « » } を設定する。
  7. previousOffsetPositionnull を設定する。
  8. previousLastMappingnull を設定する。
  9. JSON値 section について、JSONArrayIterate(sectionsField) の各要素ごとに、
    1. sectionJSON オブジェクト でなければ、
      1. オプションでエラーを報告してよい。
    2. そうでなければ、
      1. offsetJSONObjectGet(section, "offset") を設定する。
      2. offsetJSON オブジェクト でなければ、エラーをスローする。
      3. offsetLineJSONObjectGet(offset, "line") を設定する。
      4. offsetColumnJSONObjectGet(offset, "column") を設定する。
      5. offsetLine整数値 Number でなければ、
        1. オプションでエラーを報告してよい。
        2. offsetLine+0𝔽 を設定する。
      6. offsetColumn整数値 Number でなければ、
        1. オプションでエラーを報告してよい。
        2. offsetColumn+0𝔽 を設定する。
      7. offsetPosition に新しい Position Record { [[Line]]: offsetLine, [[Column]]: offsetColumn } を設定する。
      8. previousOffsetPositionnull ならば、
        1. ComparePositions(offsetPosition, previousOffsetPosition) が lesser の場合、オプションでエラーを報告してよい。
      9. previousLastMappingnull ならば、
        1. ComparePositions(offsetPosition, previousLastMapping.[[GeneratedPosition]]) が lesser の場合、オプションでエラーを報告してよい。
        2. 注: この箇所でのデコードアルゴリズムは index ソースマップの sections フィールド のエントリが順序付きで重複していないことを検証する。ジェネレーターが重複する section を持つ index source map を生成することは想定されていないが、source map の利用側は、例えば section の offset が順序付きであるかの簡易的な条件のみをチェックする場合がある。
      10. mapFieldJSONObjectGet(section, "map") を設定する。
      11. mapFieldJSON オブジェクト でなければ、エラーをスローする。
      12. decodedSectionCompletionCompletion(DecodeSourceMap(json, baseURL)) を設定する。
      13. decodedSectionCompletionthrow completion であれば、
        1. オプションでエラーを報告してよい。
      14. そうでなければ、
        1. decodedSectiondecodedSectionCompletion.[[Value]] を設定する。
        2. Decoded Source Record additionalSource について、decodedSection.[[Sources]] の全要素で、
          1. sourceMap.[[Sources]]additionalSource が含まれていなければ、
            1. additionalSourcesourceMap.[[Sources]] に追加する。
        3. offsetMappings に新しい空の リスト を設定する。
        4. Decoded Mapping Record mapping について、decodedSection.[[Mappings]] の全要素で、
          1. mapping.[[GeneratedPosition]].[[Line]] = 0 の場合、
            1. mapping.[[GeneratedPosition]].[[Column]]mapping.[[GeneratedPosition]].[[Column]] + offsetColumn を設定する。
          2. mapping.[[GeneratedPosition]].[[Line]]mapping.[[GeneratedPosition]].[[Line]] + offsetLine を設定する。
          3. mappingoffsetMappings に追加する。
        5. sourceMap.[[Mappings]]リスト結合 によって sourceMap.[[Mappings]]offsetMappings を設定する。
        6. previousOffsetPositionoffsetPosition を設定する。
        7. offsetMappings が空でなければ、previousLastMappingoffsetMappings の最後の要素を設定する。
    3. sourceMap を返す。
実装によっては、マッピングを連結せず各sectionを個別に保存しバイナリサーチするなどの方法も選択できます。

11 ソースマップの取得

11.1 生成コードとソースマップのリンク

ソースマップ形式は言語やプラットフォームに依存しないことを意図していますが、ウェブサーバでホストされる JavaScript という想定されたユースケースに対してどのように参照されるかを定義することは有用です。

ソースマップを出力にリンクする方法は2つあります。1つ目はHTTPヘッダーの追加のためサーバーの対応が必要で、2つ目はソース内にアノテーションを書く方法です。

ソースマップは WHATWG URL で定義される URL を使ってリンクされます。特に、URI に使えない文字はパーセントエンコードされる必要があり、data URI であってもかまいません。sourcesContent と共に data URI を使用することで、完全に自己完結したソースマップが可能になります。

HTTP の sourcemap ヘッダーはソース注記よりも優先され、両方が存在する場合は、ヘッダーの URL を使ってソースマップファイルを解決すべきです。

ソースマップURL を取得する方法にかかわらず、解決処理は同じであり、手順は下記の通りです。

ソースマップURL が絶対URLでない場合、生成コードソースオリジン を基準とします。ソースオリジン は次のいずれかのケースで決定されます:

  • 生成されたソースが src 属性を持つ script 要素に関連付けられていない状態で、生成コード 内に //# sourceURL コメントが存在する場合、そのコメントによって ソースオリジン を決定します。

    以前はこの記法は //@ sourceURL でした。//@ sourceMappingURL の場合と同様に、どちらも受け入れてかまいませんが、//# の方が推奨されます。
  • 生成コード が script 要素に関連付けられており、その script 要素が src 属性を持つ場合は、script 要素の src 属性が ソースオリジン となります。
  • 生成コード が script 要素に関連付けられているが、その script 要素が src 属性を持たない場合、ソースオリジン はページのオリジンとなります。
  • 生成コードeval() 関数や new Function() により文字列として評価されている場合、ソースオリジン はページのオリジンとなります。

11.1.1 HTTPヘッダーによるリンク

ファイルがHTTP(S)でsourcemapヘッダー付きで配信される場合、ヘッダーの値がリンクされるソースマップのURLになります。

sourcemap: <url>
従来の文書改訂ではヘッダー名x-sourcemapを推奨していましたが、現在は非推奨でsourcemapの利用が期待されます。

11.1.2 インラインアノテーションによるリンク

生成コード には、sourceMappingURL という名前のコメント(またはその言語やフォーマットに応じた同等の構文)を含め、その中にソースマップの URL を記述する必要があります。本仕様は JavaScript、CSS、および WebAssembly においてコメントがどのような形式になるべきかを定義します。他の言語も同様の方式に従うべきです。

特定言語においては sourceMappingURL コメントの検出方法が複数あり得ます。さまざまな実装がそれぞれにとってより複雑でないものを選択できるようにするためです。生成コード一意にソースマップへリンクする とは、すべての抽出法の結果が同じとなる場合を指します。

ツールが 一意にソースマップへリンクする 1つ以上のソースファイルを消費し、ソースマップをリンクする出力ファイルを生成する場合、出力も 一意にリンクしなければなりません。

以下の JavaScript コードはソースマップへリンクしていますが、一意にはリンクしていません:

let a = `
//# sourceMappingURL=foo.js.map
// `

これから ソースマップURLパースで抽出 した場合は foo.js.map であり、パースなしで抽出 した場合は null となります。

11.1.2.1 JavaScriptExtractSourceMapURL ( source )

抽象操作 JavaScriptExtractSourceMapURL は引数 source(String 型)をとり、 String または null を返す。これは JavaScript ソースからソースマップURL を抽出する。 実装には パースによる方法パースなしの方法 の2通りがある。

ソースマップURLパースによって抽出 するには:

  1. tokens に、sourceECMA-262 字句構文 でパースして得られる リスト入力要素 のリスト)を設定する。
  2. tokens の各非終端要素 token について、逆順で繰り返す:
    1. tokenSingleLineCommentWhiteSpaceLineTerminatorSequence のいずれでもなければ null を返す。
    2. commenttoken の内容を設定する。
    3. sourceMapURLMatchSourceMapURL(comment) を設定する。
    4. sourceMapURLString の場合sourceMapURL を返す。
  3. null を返す。

ソースマップURLパースなしで抽出 するには:

  1. linesStringSplit(source, « "\u000D\u000A", "\u000A", "\u000D", "\u2028", "\u2029" ») を設定する。
  2. 注: 上記の文字列リストは LineTerminatorSequence の生成規則に対応する。
  3. lines の各 String lineStr について、逆順で繰り返す:
    1. lineStringToCodePoints(lineStr) を設定する。
    2. position に 0 を設定する。
    3. lineLengthline の長さを設定する。
    4. position < lineLength の間、繰り返し:
      1. firstline[position] を設定する。
      2. もし first が U+002F (SOLIDUS) かつ position + 1 < lineLength なら、
        1. positionposition + 1 を設定する。
        2. secondline[position] を設定する。
        3. second が U+002F (SOLIDUS) の場合、
          1. positionposition + 1 を設定する。
          2. commentlineStrsubstringposition から lineLength まで)を設定する。
          3. comment に U+0022(引用符)、U+0027(アポストロフィ)、U+0060(グレイブアクセント)のいずれかのコードポイントが含まれていれば、
            1. null を返す。
          4. comment にコードポイント U+002A(アスタリスク)直後に U+002F(SOLIDUS)が含まれていれば、
            1. null を返す。
          5. sourceMapURLMatchSourceMapURL(comment) を設定する。
          6. sourceMapURLString の場合sourceMapURL を返す。
          7. positionlineLength を設定する。
        4. それ以外の場合、
          1. null を返す。
      3. それ以外で first が ECMAScript の WhiteSpace の場合、
        1. positionposition + 1 を設定する。
      4. それ以外は、
        1. null を返す。
  4. null を返す。

source がパースエラーなくパースでき、かつ ソースマップURLパースなし で抽出して非 null ならば、パースで抽出した時も同じ結果になる。

11.1.2.1.1 MatchSourceMapURL ( comment )

抽象演算MatchSourceMapURLは引数comment(String型)を受け取り、noneまたはStringを返します。呼び出し時は以下の手順:

  1. patternRegExpCreate("^[@#]\s*sourceMappingURL=(\S*?)\s*$", "")とする。
  2. matchRegExpExec(pattern, comment)とする。
  3. matchnullでなければ、Get(match, "1")を返す。
  4. noneを返す。
このアノテーションの接頭辞は最初は//@でしたが、IEの条件付きコンパイルと競合するため//#に変更されました。

ソースマップ生成ツールは//#のみ出力すべきですが、利用側は//@//#の両方を受け入れるべきです。

11.1.2.2 CSSExtractSourceMapURL ( source )

抽象操作 CSSExtractSourceMapURL は引数 source(String 型)を取り、String または null を返す。これは CSS ソースから ソースマップURL を抽出する。

ソースマップURL の抽出はJavaScriptと似ているが、CSSでは /* ... */ 型コメントのみがサポートされている点が異なる。

11.1.2.3 WebAssemblyExtractSourceMapURL ( bytes )

抽象演算WebAssemblyExtractSourceMapURLは引数bytesData Block型)を受け取り、Stringまたはnullを返します。WebAssemblyバイナリソースからソースマップURLを抽出します。

  1. modulemodule_decode(bytes) を設定する。
  2. moduleWebAssembly エラー ならば、null を返す。
  3. module の各 カスタムセクション customSection について、
    1. namecustomSectionname を設定する。
    2. CodePointsToString(name) が "sourceMappingURL" ならば、
      1. valuecustomSectionbytes を設定する。
      2. CodePointsToString(value) を返す。
  4. null を返す。

WebAssembly はテキスト形式ではなく、コメントもサポートしていないため、ひとつの明確な抽出法のみをサポートする。URLWebAssembly の名前 としてエンコードされ、カスタムセクション の内容として配置される。sourceMappingURL という名前の カスタムセクション を2つ以上生成することは、WebAssembly コード生成ツールにとって不正である。

11.2 ソースマップの取得処理

11.2.1 FetchSourceMap ( url )

抽象操作 FetchSourceMap は、引数 urlURL 型)を取り、 Promise を返す。呼び出されたとき、次のステップを実行する:

  1. promiseCapabilityNewPromiseCapability(%Promise%) を設定する。
  2. requestrequest の新しいインスタンスで、その request URLurl とするものを設定する。
  3. processResponseConsumeBody抽象クロージャ(パラメータ (response, bodyBytes)、promiseCapabilityurl をキャプチャ)の新しいインスタンスを設定し、呼び出されたら次を実行:
    1. bodyBytesnull または failure であれば、
      1. Call(promiseCapability.[[Reject]], undefined, « 新しい TypeError » ) を実行する。
      2. return。
    2. urlスキームHTTP(S) スキーム であり、 バイト列 `)]}'` が バイト列接頭辞 として bodyBytes に現れる場合、
      1. 繰り返し、bodyBytes長さ ≠ 0 かつ bodyBytes[0] が HTTP 改行バイト ではない間、
        1. bodyBytes の 0 番目の要素を除去する。
    3. bodyStringCompletion(UTF-8 デコード(bodyBytes)) を設定する。
    4. IfAbruptRejectPromise(bodyString, promiseCapability) を実行。
    5. jsonValueCompletion(ParseJSON(bodyString)) を設定する。
    6. IfAbruptRejectPromise(jsonValue, promiseCapability) を実行。
    7. Call(promiseCapability.[[Resolve]], undefined, « jsonValue » ) を実行する。
  4. fetchrequest を発行し、processResponseConsumeBodyprocessResponseConsumeBody に設定する。
  5. promiseCapability.[[Promise]] を返す。

歴史的な理由から、HTTP(S) でソースマップを配信する際に、サーバが )]}' で始まる行を ソースマップの先頭に付加する場合がある。

)]}'garbage here
{"version": 3, ...}

これは次のように解釈される:

{"version": 3, ...}

12 ソースマップレコードの操作

ソースマップをデコードした後、ソースマップ利用者は得られた Decoded Source Map Records を使ってデバッグなどの用途で位置情報を調べることができます。このセクションでは、ソースマップ利用者がサポートするであろう典型的な操作の挙動について説明します。

GetOriginalPositions 操作は、生成コード中のある位置に対応する 元のソース の位置を問い合わせるために使うことができます。たとえばデバッガで 生成コード 上のユーザーのマウスクリックから 元のソース 側にジャンプする用途などに利用されます。

12.1 GetOriginalPositions ( sourceMapRecord, generatedPosition )

抽象操作 GetOriginalPositions は、引数 sourceMapRecordDecoded Source Map Record)と generatedPositionPosition Record)を取り、 リストOriginal Position Recordsのリスト)を返す。呼び出されたとき、次のステップを実行する:

  1. mappingssourceMapRecord.[[Mappings]] を設定する。
  2. lastnull を設定する。
  3. originalPositions に新しい空の リスト を設定する。
  4. mappings の各要素 mapping について、逆順で繰り返す:
    1. lastnull ならば、
      1. ComparePositions(mapping.[[GeneratedPosition]], generatedPosition) の結果が lesser または equal ならば、
        1. lastmapping を設定する。
  5. lastnull でなければ、
    1. mappings の各要素 mapping について、繰り返す:
      1. ComparePositions(last.[[GeneratedPosition]], mapping.[[GeneratedPosition]]) の結果が equal ならば、
        1. mapping.[[OriginalPosition]]originalPositions に追加する。
  6. originalPositions を返す。

Annex A (informative) 慣例

ソースマップの取扱いや生成時には次の慣例に従うべきです。

A.1 ソースマップ命名規則

一般的に、ソースマップは生成されたファイル名に.map拡張子をつけ同名で作成されます。例:page.jsの場合、page.js.mapというソースマップが生成されます。

A.2 evalコードの名前付き生成コードへのリンク

evalコードにソースマップを利用するための既存の慣例があり、次の形式を取ります:

//# sourceURL=foo.js

これはGive your eval a name with //@ sourceURLで説明されています。

Annex B (informative) 注釈

B.1 言語非依存のスタックマッピング

ソース言語の知識なしでのスタックトレースマッピングは本書では対象外です。

B.2 多段階マッピング

DSL(テンプレート)からの生成やTypeScript → JavaScript → minified JavaScriptといった複数段の変換を経た最終ソースマップが生成されるケースが一般的になっています。この問題は二通りで対応可能です。一つは単純ですが情報損失が発生する方法で、中間ステップをデバッグ用途では無視し、翻訳過程の位置情報を無視して(中間変換を「元ソース」とみなす)、または位置情報を引き継いで(中間変換は隠される)扱う方法です。より完全な方法は多段階のマッピングをサポートするものです。元ソース側もソースマップ参照を持つ場合、ユーザーはそれも利用可能です。

ただし、JavaScript以外で「ソースマップ参照」が何なのかは未定義です。特に、JavaScript形式の一行コメントをサポートしない言語でソースマップ参照がどんな形式になるかは不明です。

Annex C (informative) 他仕様で定義されている用語

本書で使われている用語・アルゴリズムのうち、ECMA-262以外の外部仕様で定義されるものを列挙します。

WebAssembly Core Specification <https://www.w3.org/TR/wasm-core-2/>
custom section, module_decode, WebAssembly error, WebAssembly names
WHATWG Encoding <https://encoding.spec.whatwg.org/>
UTF-8 decode
WHATWG Fetch <https://fetch.spec.whatwg.org/>
fetch, HTTP newline byte, processResponseConsumeBody, request, request URL
WHATWG Infra <https://infra.spec.whatwg.org/>
byte sequence, byte-sequence-prefix, byte-sequence-length,
WHATWG URL <https://url.spec.whatwg.org/>
HTTP(S) scheme, scheme, URL, URL parsing

Annex D (informative) 参考文献

  1. IETF RFC 4648, The Base16, Base32, and Base64 Data Encodings, available at <https://datatracker.ietf.org/doc/html/rfc4648>
  2. ECMA-262, ECMAScript® Language Specification, available at <https://tc39.es/ecma262/>
  3. ECMA-404, The JSON Data Interchange Format, available at <https://www.ecma-international.org/publications-and-standards/standards/ecma-404/>
  4. WebAssembly Core Specification, available at <https://www.w3.org/TR/wasm-core-2/>
  5. WHATWG Encoding, available at <https://encoding.spec.whatwg.org/>
  6. WHATWG Fetch, available at <https://fetch.spec.whatwg.org/>
  7. WHATWG Infra, available at <https://infra.spec.whatwg.org/>
  8. WHATWG URL, available at <https://url.spec.whatwg.org/>
  9. Give your eval a name with //@ sourceURL, Firebug (2009), available at <http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/>
  10. Source Map Revision 2 Proposal, John Lenz (2010), available at <https://docs.google.com/document/d/1xi12LrcqjqIHTtZzrzZKmQ3lbTv9mKrN076UB-j3UZQ/>
  11. 可変長数量, Wikipedia, available at <https://en.wikipedia.org/wiki/Variable-length_quantity>

Annex E (informative) コロフォン

この仕様書は、GitHub上で、Ecmarkupというプレーンテキストソース形式で作成されています。EcmarkupはHTMLとMarkdownの方言であり、プレーンテキストでECMAScript仕様書を執筆し、文書の編集上の慣例に従った本格的なHTMLレンダリングへと処理できるフレームワークとツールセットを提供します。Ecmarkupは、構文定義用のGrammarkdownや、アルゴリズム手順記述用のEcmarkdownなど、様々なフォーマットや技術を統合しています。この仕様書のPDFレンダリングは、HTMLレンダリングをPDF印刷することで作成されています。

この仕様書の初版は、Bikeshedという、HTMLとMarkdownをベースにした別のプレーンテキストソース形式で作成されました。

標準化以前のバージョンはGoogle Docsで執筆されました。

Copyright & Software License

Ecma International

Rue du Rhone 114

CH-1204 Geneva

Tel: +41 22 849 6000

Fax: +41 22 849 6001

Web: https://ecma-international.org/

Software License

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.