Multipage preference

Draft ECMA-426 / August 10, 2026

Source map format specification

이 명세에 관하여

https://tc39.es/ecma426/의 문서는 가장 정확하고 최신인 소스 맵 명세이다. 이 문서는 가장 최근에 공개된 스냅샷의 내용과 다음 스냅샷에 포함될 모든 변경 사항을 포함한다.

이 명세에 기여하기

이 명세는 GitHub에서 개발된다. 이 명세의 개발에 기여하는 방법에는 여러 가지가 있다:

이 문서가 어떻게 생성되는지에 대한 자세한 내용은 콜로폰을 참조하라.

소개

이 Ecma 표준은 트랜스파일된 소스 코드를 원본 소스로 다시 매핑하는 데 사용되는 소스 맵 형식을 정의한다.

소스 맵 형식은 다음 목표를 가진다:

원본 소스 맵 형식(v1)은 Joseph Schorr가 Closure Inspector에서 최적화된 JavaScript 코드의 소스 수준 디버깅을 가능하게 하기 위해 만들었다(형식 자체는 언어에 독립적이다). 그러나 소스 맵을 사용하는 프로젝트의 규모가 커지면서, 형식의 장황함이 문제가 되기 시작했다. 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® Language Specification.
https://tc39.es/ecma262/

ECMA-404, The JSON Data Interchange Format.
https://www.ecma-international.org/publications-and-standards/standards/ecma-404/

3.2 정보성 참조

IETF RFC 4648, The Base16, Base32, and Base64 Data Encodings.
https://datatracker.ietf.org/doc/html/rfc4648

WebAssembly Core Specification.
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: an integer, ): an integer

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS.

다음과 동등하다:

4.1.1.2 GetTheAnswer2 ( input: an integer, ): either a normal completion containing an integer or a throw completion

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS.

완료 레코드를 반환하는 추상 연산에 대한 모든 호출은 명시적인 Completion 호출로 감싸지지 않은 한, ECMA-262의 ? 완료 레코드 언래핑 약식으로 감싸졌다고 암시적으로 가정한다. 예를 들면 다음과 같다:

#### ECMARKDOWN PARSE FAILED ####
        1. _result_를 GetTheAnswer(_value_)로 둔다.
        1. _second_를 Completion(GetTheAnswer(_value_))로 둔다.
      

이는 다음과 동등하다:

#### ECMARKDOWN PARSE FAILED ####
        1. _result_를 ? GetTheAnswer(_value_)로 둔다.
        1. _second_를 Completion(GetTheAnswer(_value_))로 둔다.
      

4.1.2 선택적 오류

알고리즘이 오류를 선택적으로 보고해야 할 때마다, 구현은 다음 동작 중 하나를 선택할 수 있다:

  • 알고리즘의 나머지를 계속 실행한다.
  • 사용자에게 오류를 보고하고(예: 브라우저 콘솔), 알고리즘의 나머지를 계속 실행한다.
  • ThrowCompletion을 반환한다.

구현은 서로 다른 선택적 오류에 대해 서로 다른 동작을 선택할 수 있다.

4.2 문법 표기

이 명세는 다음 주의 사항을 포함하여, ECMA-262(문법 표기)에서 정의한 것과 동일한 문법 표기 규칙을 따른다:

  • 이 명세에서 정의된 문법의 단말 기호는 개별 코드 포인트이다. 이는 ECMA-262의 어휘 문법과 유사하며, ECMA-262의 구문 문법과는 다르다.
  • 이 명세는 문법 정의의 복잡성을 줄이기 위해 문법 매개변수 또는 lookahead 제한을 사용하지 않는다.

5 용어와 정의

이 문서의 목적상, 다음 용어와 정의가 적용된다.

생성된 코드

컴파일러 또는 트랜스파일러에 의해 생성된 코드.

원본 소스

컴파일러 또는 트랜스파일러를 거치지 않은 소스 코드.

소스 맵 URL

생성된 코드에서 소스 맵의 위치를 참조하는 URL.

생성된 코드의 한 줄 안에서 0부터 시작하는 인덱스 오프셋으로, JavaScript와 CSS 소스 맵에서는 UTF-16 코드 단위로 계산되며, WebAssembly 소스 맵에서는 바이너리 콘텐츠(단일 줄로 표현됨)의 바이트 인덱스로 계산된다.

Note
이는 “A”(LATIN CAPITAL LETTER A)가 1 코드 단위로 측정되고, “🔥”(FIRE)가 2 코드 단위로 측정됨을 의미한다. 다른 콘텐츠 유형의 소스 맵은 이와 다를 수 있다.

6 base64 VLQ

base64 VLQbase64로 인코딩된 가변 길이 수량이며, 여기서 최상위 비트(6번째 비트)는 연속 비트로 사용되고, “digits”는 최하위부터 문자로 인코딩되며, 첫 번째 digit의 최하위 비트는 부호 비트로 사용된다.

Note 1
base64 VLQ 인코딩으로 표현할 수 있는 값은 더 큰 값에 대한 사용 사례가 제시될 때까지 32비트 수량으로 제한된다. 이는 32비트를 초과하는 값이 유효하지 않으며 구현이 이를 거부할 수 있음을 의미한다. 부호 비트는 제한에 포함되지만, 연속 비트는 포함되지 않는다.
Note 2
문자 "iB"는 두 digit을 가진 base64 VLQ를 나타낸다. 첫 번째 digit "i"는 비트 패턴 0b100010을 인코딩하며, 이는 연속 비트 1(VLQ가 계속됨), 부호 비트 0(음수가 아님), 값 비트 0b0001을 가진다. 두 번째 digit B는 비트 패턴 0b000001을 인코딩하며, 이는 연속 비트 0, 부호 비트 없음, 값 비트 0b00001을 가진다. 이 VLQ 문자을 디코딩한 값은 숫자 17이다.
Note 3
문자 "V"는 하나의 digit을 가진 base64 VLQ를 나타낸다. digit "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

The syntax-directed operation VLQSignedValue takes no arguments and returns an integer. It is defined piecewise over the following productions:

Vlq :: VlqDigitList #### ECMARKDOWN PARSE FAILED ####
      1. _unsigned_를 |VlqDigitList|의 VLQUnsignedValue로 둔다.
      1. _unsigned_ modulo 2 = 1이면, _sign_을 -1로 둔다.
      1. 그렇지 않으면, _sign_을 1로 둔다.
      1. _value_를 floor(_unsigned_ / 2)로 둔다.
      1. _value_가 0이고 _sign_이 -1이면, -231을 반환한다.
      1. [id="step-VLQSignedValue-boundary-check"] _value_가 ≥ 231이면, 오류를 throw한다.
      1. _sign_ × _value_를 반환한다.
    
Note
단계의 검사가 필요한 이유는 unsignedVlq가 아니라 VlqDigitListVLQUnsignedValue이기 때문이다.

6.2 VLQUnsignedValue

The syntax-directed operation VLQUnsignedValue takes no arguments and returns an non-negative integer. It is defined piecewise over the following productions:

Vlq :: VlqDigitList #### ECMARKDOWN PARSE FAILED ####
      1. _value_를 |VlqDigitList|의 VLQUnsignedValue로 둔다.
      1. _value_가 ≥ 232이면, 오류를 throw한다.
      1. _value_를 반환한다.
    
VlqDigitList :: ContinuationDigit VlqDigitList #### ECMARKDOWN PARSE FAILED ####
      1. _left_를 |ContinuationDigit|의 VLQUnsignedValue로 둔다.
      1. _right_를 |VlqDigitList|의 VLQUnsignedValue로 둔다.
      1. _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 #### ECMARKDOWN PARSE FAILED ####
      1. _digit_을 이 production과 일치한 문자로 둔다.
      1. _value_를 IETF RFC 4648에서 정의한 base64 인코딩에 따라 _digit_에 대응하는 정수로 둔다.
      1. Assert: _value_ < 32.
      1. _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 + / #### ECMARKDOWN PARSE FAILED ####
      1. _digit_을 이 production과 일치한 문자로 둔다.
      1. _value_를 IETF RFC 4648에서 정의한 base64 인코딩에 따라 _digit_에 대응하는 정수로 둔다.
      1. Assert: 32 ≤ _value_ < 64.
      1. _value_ - 32를 반환한다.
    

7 JSON 값 유틸리티

이 명세의 알고리즘은 ECMA-262 내부 구조 위에서 정의되지만, JavaScript가 아닌 플랫폼에서도 쉽게 구현할 수 있도록 의도되었다. 이 절은 JSON 값으로 작업하기 위한 유틸리티를 포함하며, 문서의 나머지 부분에서 ECMA-262 세부사항을 추상화한다.

JSON 값JSON 객체, JSON 배열, String, Number, Boolean, 또는 null 중 하나이다.

JSON 객체는 그 각 프로퍼티가 다음을 만족하는 Object이다:

JSON 배열은 다음을 만족하는 JSON 객체이다:

7.1 ParseJSON ( string: a String, ): a JSON value

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
      1. _result_를 Call(%JSON.parse%, *null*, « _string_ »)로 둔다.
      1. Assert: _result_는 JSON 값이다.
      1. _result_를 반환한다.
    
Editor's Note
이 추상 연산은 tc39/ecma262#3540에서 ECMA-262 자체에 의해 노출되는 과정에 있다.

7.2 JSONObjectGet ( object: a JSON object, key: a String, ): a JSON value or missing

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
      1. _object_가 키 _key_를 가진 자체 프로퍼티를 가지지 않으면, ~missing~을 반환한다.
      1. _prop_을 키가 _key_인 _object_의 자체 프로퍼티로 둔다.
      1. _prop_의 [[Value]] 속성을 반환한다.
    

7.3 JSONArrayIterate ( array: a JSON array, ): a List of JSON values

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
      1. _length_를 JSONObjectGet(_array_, *"length"*)로 둔다.
      1. Assert: _length_는 음수가 아닌 정수 Number이다.
      1. _list_를 새 빈 List로 둔다.
      1. _i_를 0으로 둔다.
      1. _i_ < ℝ(_length_)인 동안 반복한다.
        1. _value_를 JSONObjectGet(_array_, ToString(𝔽(_i_)))로 둔다.
        1. Assert: _value_는 ~missing~이 아니다.
        1. _value_를 _list_에 append한다.
        1. _i_를 _i_ + 1로 설정한다.
      1. _list_를 반환한다.
    

7.4 StringSplit ( string: a String, separators: a List of non-empty Strings, ): a List of Strings

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
      1. _parts_를 새 빈 List로 둔다.
      1. _strLen_을 _string_의 길이로 둔다.
      1. _lastStart_를 0으로 둔다.
      1. _i_를 0으로 둔다.
      1. _i_ < _strLen_인 동안 반복한다.
        1. _matched_를 *false*로 둔다.
        1. 각 String _sep_에 대해 _separators_에서 다음을 수행한다.
          1. _sepLen_을 _sep_의 길이로 둔다.
          1. _candidate_를 _string_에서 _i_부터 min(_i_ + _sepLen_, _strLen_)까지의 부분 문자열로 둔다.
          1. _candidate_ = _sep_이고 _matched_가 *false*이면,
            1. _chunk_를 _string_에서 _lastStart_부터 _i_까지의 부분 문자열로 둔다.
            1. _chunk_를 _parts_에 append한다.
            1. _lastStart_를 _i_ + _sepLen_으로 설정한다.
            1. _i_를 _i_ + _sepLen_으로 설정한다.
            1. _matched_를 *true*로 설정한다.
        1. _matched_가 *false*이면, _i_를 _i_ + 1로 설정한다.
      1. _chunk_를 _string_에서 _lastStart_부터 _strLen_까지의 부분 문자열로 둔다.
      1. _chunk_를 _parts_에 append한다.
      1. _parts_를 반환한다.
    

8 위치 타입

8.1 Position Record

Position Record는 음수가 아닌 줄 번호와 음수가 아닌 번호의 튜플이다:

Table 1: Position Record Fields
필드 이름 값 타입
[[Line]] 음수가 아닌 정수 Number
[[Column]] 음수가 아닌 정수 Number

8.2 Original Position Record

Original Position RecordDecoded Source Record, 음수가 아닌 줄 번호, 음수가 아닌 번호의 튜플이다. 이는 Position Record와 유사하지만 구체적인 원본 소스 파일 안의 소스 위치를 설명한다.

Table 2: Original Position Record Fields
필드 이름 값 타입
[[Source]] Decoded Source Record
[[Line]] 음수가 아닌 정수 Number
[[Column]] 음수가 아닌 정수 Number

8.3 ComparePositions ( first: a Position Record or a Original Position Record, second: a Position Record or a Original Position Record, ): lesser, equal or greater

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
      1. _first_.[[Line]] < _second_.[[Line]]이면, ~lesser~를 반환한다.
      1. _first_.[[Line]] > _second_.[[Line]]이면, ~greater~를 반환한다.
      1. Assert: _first_.[[Line]]은 _second_.[[Line]]과 같다.
      1. _first_.[[Column]] < _second_.[[Column]]이면, ~lesser~를 반환한다.
      1. _first_.[[Column]] > _second_.[[Column]]이면, ~greater~를 반환한다.
      1. ~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 소스 맵 디코딩

Decoded Source Map Record는 다음 필드를 가진다:

Table 3: Fields of Decoded Source Map Records
필드 이름 값 타입
[[File]] String 또는 null
[[Sources]] Decoded Source RecordsList
[[Mappings]] Decoded Mapping RecordsList

Decoded Source Record는 다음 필드를 가진다:

Table 4: Fields of Decoded Source Records
필드 이름 값 타입
[[URL]] URL 또는 null
[[Content]] String 또는 null
[[Ignored]] Boolean

9.1.1 ParseSourceMap ( string: a String, baseURL: an URL, ): a Decoded Source Map Record

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
        1. _json_을 ParseJSON(_string_)으로 둔다.
        1. _json_이 JSON 객체가 아니면, 오류를 throw한다.
        1. JSONObjectGet(_json_, *"sections"*)가 ~missing~이 아니면,
          1. DecodeIndexSourceMap(_json_, _baseURL_)을 반환한다.
        1. DecodeSourceMap(_json_, _baseURL_)을 반환한다.
      

9.1.2 DecodeSourceMap ( json: a JSON object, baseURL: an URL, ): a Decoded Source Map Record

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
        1. JSONObjectGet(_json_, *"version"*)가 *3*𝔽가 아니면, 오류를 선택적으로 보고한다.
        1. _mappingsField_를 JSONObjectGet(_json_, *"mappings"*)로 둔다.
        1. _mappingsField_가 String이 아니면, 오류를 throw한다.
        1. JSONObjectGet(_json_, *"sources"*)가 JSON 배열이 아니면, 오류를 throw한다.
        1. _fileField_를 GetOptionalString(_json_, *"file"*)로 둔다.
        1. _sourceRootField_를 GetOptionalString(_json_, *"sourceRoot"*)로 둔다.
        1. _sourcesField_를 GetOptionalListOfOptionalStrings(_json_, *"sources"*)로 둔다.
        1. _sourcesContentField_를 GetOptionalListOfOptionalStrings(_json_, *"sourcesContent"*)로 둔다.
        1. _ignoreListField_를 GetOptionalListOfArrayIndexes(_json_, *"ignoreList"*)로 둔다.
        1. _sources_를 DecodeSourceMapSources(_baseURL_, _sourceRootField_, _sourcesField_, _sourcesContentField_, _ignoreListField_)로 둔다.
        1. _namesField_를 GetOptionalListOfStrings(_json_, *"names"*)로 둔다.
        1. _mappings_를 DecodeMappings(_mappingsField_, _namesField_, _sources_)로 둔다.
        1. [declared="a,b"] Decoded Mapping Record _a_가 Decoded Mapping Record _b_보다 작은 경우를 ComparePositions(_a_.[[GeneratedPosition]], _b_.[[GeneratedPosition]])가 ~lesser~인 경우로 하여, _mappings_를 오름차순으로 정렬한다.
        1. Decoded Source Map Record { [[File]]: _fileField_, [[Sources]]: _sources_, [[Mappings]]: _mappings_ }를 반환한다.
      

9.1.2.1 GetOptionalString ( object: a JSON object, key: a String, ): a String or null

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
          1. _value_를 JSONObjectGet(_object_, _key_)로 둔다.
          1. _value_가 String이면, _value_를 반환한다.
          1. _value_가 ~missing~이 아니면, 오류를 선택적으로 보고한다.
          1. *null*을 반환한다.
        

9.1.2.2 GetOptionalListOfStrings ( object: a JSON object, key: a String, ): a List of Strings

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
          1. _list_를 새 빈 List로 둔다.
          1. _values_를 JSONObjectGet(_object_, _key_)로 둔다.
          1. _values_가 ~missing~이면, _list_를 반환한다.
          1. _values_가 JSON 배열이 아니면,
            1. 오류를 선택적으로 보고한다.
            1. _list_를 반환한다.
          1. JSONArrayIterate(_values_)의 각 요소 _item_에 대해 다음을 수행한다.
            1. _item_이 String이면,
              1. _item_을 _list_에 append한다.
            1. 그렇지 않으면,
              1. 오류를 선택적으로 보고한다.
              1. 빈 String을 *list*에 추가한다.
          1. _list_를 반환한다.
        

9.1.2.3 GetOptionalListOfOptionalStrings ( object: a JSON object, key: a String, ): a List of either Strings or null

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
          1. _list_를 새 빈 List로 둔다.
          1. _values_를 JSONObjectGet(_object_, _key_)로 둔다.
          1. _values_가 ~missing~이면, _list_를 반환한다.
          1. _values_가 JSON 배열이 아니면,
            1. 오류를 선택적으로 보고한다.
            1. _list_를 반환한다.
          1. JSONArrayIterate(_values_)의 각 요소 _item_에 대해 다음을 수행한다.
            1. _item_이 String이면,
              1. _item_을 _list_에 append한다.
            1. 그렇지 않으면,
              1. _item_ ≠ *null*이면, 오류를 선택적으로 보고한다.
              1. *null*을 _list_에 append한다.
          1. _list_를 반환한다.
        

9.1.2.4 GetOptionalListOfArrayIndexes ( object: an Object, key: a String, ): a List of non-negative integers

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
          1. _list_를 새 빈 List로 둔다.
          1. _values_를 JSONObjectGet(_object_, _key_)로 둔다.
          1. _values_가 ~missing~이면, _list_를 반환한다.
          1. _values_가 JSON 배열이 아니면,
            1. 오류를 선택적으로 보고한다.
            1. _list_를 반환한다.
          1. JSONArrayIterate(_values_)의 각 요소 _item_에 대해 다음을 수행한다.
            1. _item_이 정수 Number이고 _item_ ≥ *+0*𝔽이면,
              1. ℝ(_item_)을 _list_에 append한다.
            1. 그렇지 않으면,
              1. 오류를 선택적으로 보고한다.
          1. _list_를 반환한다.
        

9.2 Mappings 구조

mappings 필드 데이터는 다음과 같이 나뉜다:

  • 생성된 파일의 한 줄을 나타내는 각 그룹은 세미콜론(;)으로 구분된다
  • 각 segment는 쉼표(,)로 구분된다
  • 각 segment는 1개, 4개 또는 5개의 가변 길이 필드로 구성된다.

각 segment의 필드는 다음과 같다:

  1. segment가 나타내는 생성된 코드 줄의 0부터 시작하는 시작 . 이것이 첫 번째 segment의 첫 번째 필드이거나, 새 생성 줄(;) 뒤의 첫 번째 segment라면, 이 필드는 전체 base64 VLQ를 보유한다. 그렇지 않으면, 이 필드는 이 필드의 이전 등장에 상대적인 base64 VLQ를 포함한다. 이는 생성된 각 줄 이후에 이전 값이 재설정되므로 아래 후속 필드와 다르다는 점에 유의하라.
  2. 존재하는 경우, sources 목록으로 들어가는 0부터 시작하는 인덱스. 이 필드는 이 필드의 이전 등장에 상대적인 base64 VLQ를 포함하며, 이 필드가 처음 등장하는 경우에는 전체 값이 표현된다.
  3. 존재하는 경우, 원본 소스에서 0부터 시작하는 시작 줄. 이 필드는 이 필드의 이전 등장에 상대적인 base64 VLQ를 포함하며, 이 필드가 처음 등장하는 경우에는 전체 값이 표현된다. source 필드가 있으면 존재해야 한다.
  4. 존재하는 경우, 원본 소스의 줄에서 0부터 시작하는 시작 . 이 필드는 이 필드의 이전 등장에 상대적인 base64 VLQ를 포함하며, 이 필드가 처음 등장하는 경우에는 전체 값이 표현된다. source 필드가 있으면 존재해야 한다.
  5. 존재하는 경우, 이 segment와 연관된 names 목록으로 들어가는 0부터 시작하는 인덱스. 이 필드는 이 필드의 이전 등장에 상대적인 base64 VLQ를 포함하며, 이 필드가 처음 등장하는 경우에는 전체 값이 표현된다.
Note 1
이 인코딩의 목적은 소스 맵 크기를 줄이는 것이다. Google Calendar를 사용하여 수행한 테스트에서 VLQ 인코딩은 Source Map Revision 2 Proposal에 비해 소스 맵을 50% 줄였다.
Note 2
하나의 필드를 가진 segment는 컴파일러가 생성한 코드처럼 대응하는 원본 소스 코드가 없기 때문에 매핑되지 않은 생성된 코드를 나타내도록 의도되었다. 네 개의 필드를 가진 segment는 대응하는 이름이 없는 매핑된 코드를 나타낸다. 다섯 개의 필드를 가진 segment는 매핑된 이름도 가진 매핑된 코드를 나타낸다.
Note 3
파일 오프셋을 사용하는 방안도 고려되었지만, 플랫폼별 줄 끝 차이로 인해 원본과 정렬이 어긋나는 것을 피하기 위해 line/column 데이터를 사용하는 쪽으로 폐기되었다.

Decoded Mapping Record는 다음 필드를 가진다:

Table 5: Fields of Decoded Mapping Records
필드 이름 값 타입
[[GeneratedPosition]] Position Record
[[OriginalPosition]] Original Position Record 또는 null
[[Name]] String 또는 null

9.2.1 Mappings 문법

mappings String은 다음 문법을 따라야 한다:

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는 다음 필드를 가진다:

Table 6: Fields of Decode Mapping State Records
필드 이름 값 타입
[[GeneratedLine]] 음수가 아닌 정수
[[GeneratedColumn]] 음수가 아닌 정수
[[SourceIndex]] 음수가 아닌 정수
[[OriginalLine]] 음수가 아닌 정수
[[OriginalColumn]] 음수가 아닌 정수
[[NameIndex]] 음수가 아닌 정수

9.2.1.1 DecodeMappingsField

The syntax-directed operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It is defined piecewise over the following productions:

LineList : Line ; LineList #### ECMARKDOWN PARSE FAILED ####
          1. |Line|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
          1. _state_.[[GeneratedLine]]을 _state_.[[GeneratedLine]] + 1로 설정한다.
          1. _state_.[[GeneratedColumn]]을 0으로 설정한다.
          1. |LineList|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
        
Line : [empty] #### ECMARKDOWN PARSE FAILED ####
          1. 반환한다.
        
MappingList : Mapping , MappingList #### ECMARKDOWN PARSE FAILED ####
          1. |Mapping|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
          1. |MappingList|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
        
Mapping : GeneratedColumn #### ECMARKDOWN PARSE FAILED ####
          1. |GeneratedColumn|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
          1. _state_.[[GeneratedColumn]] < 0이면,
            1. 오류를 선택적으로 보고한다.
            1. 반환한다.
          1. _position_을 새 Position Record { [[Line]]: _state_.[[GeneratedLine]], [[Column]]: _state_.[[GeneratedColumn]] }로 둔다.
          1. _decodedMapping_을 새 DecodedMappingRecord { [[GeneratedPosition]]: _position_, [[OriginalPosition]]: *null*, [[Name]]: *null* }로 둔다.
          1. _decodedMapping_을 _mappings_에 append한다.
        
Mapping : GeneratedColumn OriginalSource OriginalLine OriginalColumn Nameopt #### ECMARKDOWN PARSE FAILED ####
          1. |GeneratedColumn|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
          1. _state_.[[GeneratedColumn]] < 0이면,
            1. 오류를 선택적으로 보고한다.
            1. 반환한다.
          1. _generatedPosition_을 새 Position Record { [[Line]]: _state_.[[GeneratedLine]], [[Column]]: _state_.[[GeneratedColumn]] }로 둔다.
          1. |OriginalSource|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
          1. |OriginalLine|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
          1. |OriginalColumn|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
          1. _state_.[[SourceIndex]] < 0 또는 _state_.[[SourceIndex]] ≥ _sources_의 요소 수 또는 _state_.[[OriginalLine]] < 0 또는 _state_.[[OriginalColumn]] < 0이면,
            1. 오류를 선택적으로 보고한다.
            1. _originalPosition_을 *null*로 둔다.
          1. 그렇지 않으면,
            1. _originalPosition_을 새 Original Position Record { [[Source]]: _sources_[_state_.[[SourceIndex]]], [[Line]]: _state_.[[OriginalLine]], [[Column]]: _state_.[[OriginalColumn]] }로 둔다.
          1. _name_을 *null*로 둔다.
          1. |Name|이 존재하면,
            1. |Name|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
            1. _state_.[[NameIndex]] < 0 또는 _state_.[[NameIndex]] ≥ _names_의 요소 수이면, 오류를 선택적으로 보고한다.
            1. 그렇지 않으면, _name_을 _names_[_state_.[[NameIndex]]]로 설정한다.
          1. _decodedMapping_을 새 DecodedMappingRecord { [[GeneratedPosition]]: _generatedPosition_, [[OriginalPosition]]: _originalPosition_, [[Name]]: _name_ }로 둔다.
          1. _decodedMapping_을 _mappings_에 append한다.
        
GeneratedColumn : Vlq #### ECMARKDOWN PARSE FAILED ####
          1. _relativeColumn_을 |Vlq|의 VLQSignedValue로 둔다.
          1. _state_.[[GeneratedColumn]]을 _state_.[[GeneratedColumn]] + _relativeColumn_으로 설정한다.
        
OriginalSource : Vlq #### ECMARKDOWN PARSE FAILED ####
          1. _relativeSourceIndex_를 |Vlq|의 VLQSignedValue로 둔다.
          1. _state_.[[SourceIndex]]를 _state_.[[SourceIndex]] + _relativeSourceIndex_로 설정한다.
        
OriginalLine : Vlq #### ECMARKDOWN PARSE FAILED ####
          1. _relativeLine_을 |Vlq|의 VLQSignedValue로 둔다.
          1. _state_.[[OriginalLine]]을 _state_.[[OriginalLine]] + _relativeLine_으로 설정한다.
        
OriginalColumn : Vlq #### ECMARKDOWN PARSE FAILED ####
          1. _relativeColumn_을 |Vlq|의 VLQSignedValue로 둔다.
          1. _state_.[[OriginalColumn]]을 _state_.[[OriginalColumn]] + _relativeColumn_으로 설정한다.
        
Name : Vlq #### ECMARKDOWN PARSE FAILED ####
          1. _relativeName_을 |Vlq|의 VLQSignedValue로 둔다.
          1. _state_.[[NameIndex]]를 _state_.[[NameIndex]] + _relativeName_으로 설정한다.
        

9.2.2 DecodeMappings ( rawMappings: a String, names: a List of Strings, sources: a List of Decoded Source Records, ): a List of Decoded Mapping Record

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
        1. _mappings_를 새 빈 List로 둔다.
        1. _mappingsNode_를 |MappingsField|를 목표 기호로 사용하여 _rawMappings_를 구문 분석할 때의 루트 Parse Node로 둔다.
        1. 구문 분석이 실패하면,
          1. 오류를 선택적으로 보고한다.
          1. _mappings_를 반환한다.
        1. _state_를 모든 필드가 0으로 설정된 새 Decode Mapping State Record로 둔다.
        1. _mappingsNode_의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
        1. _mappings_를 반환한다.
      

9.2.3 생성된 JavaScript 코드에 대한 mappings

mapping 항목을 가질 수 있는 생성된 코드 위치는 ECMAScript 어휘 문법에 따른 입력 요소의 관점에서 정의된다. Mapping 항목은 다음 중 하나를 가리켜야 한다:

9.2.4 생성된 JavaScript 코드에 대한 names

다음과 같은 경우, 소스 맵 생성기는 JavaScript 토큰에 대해 [[Name]] 필드를 가진 mapping 항목을 만들어야 한다:

  • 원본 소스 언어 구성 요소가 생성된 JavaScript 코드에 의미적으로 매핑된다.
  • 원본 소스 언어 구성 요소가 이름을 가진다.

그런 경우 mapping 항목의 [[Name]]원본 소스 언어 구성 요소의 이름이어야 한다. null이 아닌 [[Name]]을 가진 mappingnamed mapping이라고 한다.

Note 1
함수와 변수를 이름 변경하거나 즉시 호출 함수 표현식에서 함수 이름을 제거하는 minifier.

다음 거는 ECMAScript 구문 문법의 production과, 소스 맵 생성기가 named mapping을 내보내야 하는 해당 토큰 또는 비단말(프로덕션 오른쪽에 있는 것)을 나한다. 이러한 토큰에 대해 생성된 mapping 항목은 9.2.3 절을 따라야 한다.

거는 "최소한"으로 이해되어야 한다. 일반적으로 소스 맵 생성기는 추가 named mapping을 자유롭게 내보낼 수 있다.

Note 2
거는 생성기가 "should"인 토큰 외에도 named mapping을 "may"로 내보낼 수 있는 토큰도 나한다. 이는 기존 도구가 named mapping을 내보내거나 기대하는 현실을 반영한다. 중복 named mapping은 비교적 저렴하다. names로 들어가는 인덱스는 서로에 대해 상대적으로 인코딩되므로 같은 이름으로 이어지는 후속 mapping은 0(A)으로 인코딩된다.

9.3 Sources 해석

sourceRoot를 앞에 붙인 후 sources가 절대 URL이 아니면, sources는 소스 맵을 기준으로 해석된다(HTML 문서에서 script src 속성을 해석하는 것과 같다).

9.3.1 DecodeSourceMapSources ( baseURL: an URL, sourceRoot: a String or null, sources: a List of either Strings or null, sourcesContent: a List of either Strings or null, ignoreList: a List of non-negative integers, ): a List of Decoded Source Record

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
        1. _decodedSources_를 새 빈 List로 둔다.
        1. _sourcesContentCount_를 _sourcesContent_의 요소 수로 둔다.
        1. *sourceUrlPrefix*를 빈 String으로 한다.
        1. _sourceRoot_ ≠ *null*이면,
          1. _sourceRoot_가 코드 포인트 U+002F (SOLIDUS)로 끝나면,
            1. _sourceUrlPrefix_를 _sourceRoot_로 설정한다.
          1. 그렇지 않으면,
            1. _sourceUrlPrefix_를 _sourceRoot_와 *"/"*의 문자열 연결로 설정한다.
        1. _index_를 0으로 둔다.
        1. _index_ < _sources_의 길이인 동안 반복한다.
          1. _source_를 _sources_[_index_]로 둔다.
          1. _decodedSource_를 Decoded Source Record { [[URL]]: *null*, [[Content]]: *null*, [[Ignored]]: *false* }로 둔다.
          1. _source_ ≠ *null*이면,
            1. _source_를 _sourceUrlPrefix_와 _source_의 문자열 연결로 설정한다.
            1. _sourceURL_을 _baseURL_을 사용하여 _source_를 URL parsing한 결과로 둔다.
            1. _sourceURL_이 ~failure~이면, 오류를 선택적으로 보고한다.
            1. 그렇지 않으면, _decodedSource_.[[URL]]을 _sourceURL_로 설정한다.
          1. _ignoreList_가 _index_를 포함하면, _decodedSource_.[[Ignored]]를 *true*로 설정한다.
          1. _sourcesContentCount_ > _index_이면, _decodedSource_.[[Content]]를 _sourcesContent_[_index_]로 설정한다.
          1. _decodedSource_를 _decodedSources_에 append한다.
          1. _index_를 _index_ + 1로 설정한다.
        1. _decodedSources_를 반환한다.
      
Note
소스 콘텐츠 표시를 지원하지만 동일한 URL과 서로 다른 콘텐츠를 가진 여러 sources 표시를 지원하지 않는 구현은, 주어진 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는 시작 위치로 정렬되어야 하며, 표현되는 sections는 겹치지 않아야 한다.

10.1 DecodeIndexSourceMap ( json: an Object, baseURL: an URL, ): a Decoded Source Map Record

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
      1. _sectionsField_를 JSONObjectGet(_json_, *"sections"*)로 둔다.
      1. Assert: _sectionsField_는 ~missing~이 아니다.
      1. _sectionsField_가 JSON 배열이 아니면, 오류를 throw한다.
      1. JSONObjectGet(_json_, *"version"*)가 *3*𝔽가 아니면, 오류를 선택적으로 보고한다.
      1. _fileField_를 GetOptionalString(_json_, *"file"*)로 둔다.
      1. _sourceMap_을 Decoded Source Map Record { [[File]]: _fileField_, [[Sources]]: « », [[Mappings]]: « » }로 둔다.
      1. _previousOffsetPosition_을 *null*로 둔다.
      1. _previousLastMapping_을 *null*로 둔다.
      1. JSONArrayIterate(_sectionsField_)의 각 JSON 값 _section_에 대해 다음을 수행한다.
        1. _section_이 JSON 객체가 아니면,
          1. 오류를 선택적으로 보고한다.
        1. 그렇지 않으면,
          1. _offset_을 JSONObjectGet(_section_, *"offset"*)로 둔다.
          1. _offset_이 JSON 객체가 아니면, 오류를 throw한다.
          1. _offsetLine_을 JSONObjectGet(_offset_, *"line"*)로 둔다.
          1. _offsetColumn_을 JSONObjectGet(_offset_, *"column"*)로 둔다.
          1. _offsetLine_이 정수 Number가 아니면,
            1. 오류를 선택적으로 보고한다.
            1. _offsetLine_을 *+0*𝔽로 설정한다.
          1. _offsetColumn_이 정수 Number가 아니면,
            1. 오류를 선택적으로 보고한다.
            1. _offsetColumn_을 *+0*𝔽로 설정한다.
          1. _offsetPosition_을 새 Position Record { [[Line]]: _offsetLine_, [[Column]]: _offsetColumn_ }로 둔다.
          1. _previousOffsetPosition_ ≠ *null*이면,
            1. ComparePositions(_offsetPosition_, _previousOffsetPosition_)가 ~lesser~이면, 오류를 선택적으로 보고한다.
          1. _previousLastMapping_ ≠ *null*이면,
            1. ComparePositions(_offsetPosition_, _previousLastMapping_.[[GeneratedPosition]])가 ~lesser~이면, 오류를 선택적으로 보고한다.
            1. NOTE: 디코딩 알고리즘의 이 부분은 인덱스 소스 맵의 sections 필드 항목이 정렬되어 있고 겹치지 않는지 검사한다. 생성기가 겹치는 sections를 가진 인덱스 소스 맵을 생성하지 않아야 한다고 기대되지만, 소스 맵 소비자는 예를 들어 section 오프셋이 정렬되어 있다는 더 단순한 조건만 검사할 수 있다.
          1. _mapField_를 JSONObjectGet(_section_, *"map"*)로 둔다.
          1. _mapField_가 JSON 객체가 아니면, 오류를 throw한다.
          1. _decodedSectionCompletion_을 Completion(DecodeSourceMap(_json_, _baseURL_))으로 둔다.
          1. _decodedSectionCompletion_이 throw 완료이면,
            1. 오류를 선택적으로 보고한다.
          1. 그렇지 않으면,
            1. _decodedSection_을 _decodedSectionCompletion_.[[Value]]로 둔다.
            1. _decodedSection_.[[Sources]]의 각 Decoded Source Record _additionalSource_에 대해 다음을 수행한다.
              1. _sourceMap_.[[Sources]]가 _additionalSource_를 포함하지 않으면,
                1. _additionalSource_를 _sourceMap_.[[Sources]]에 append한다.
            1. _offsetMappings_를 새 빈 List로 둔다.
            1. _decodedSection_.[[Mappings]]의 각 Decoded Mapping Record _mapping_에 대해 다음을 수행한다.
              1. _mapping_.[[GeneratedPosition]].[[Line]] = 0이면,
                1. _mapping_.[[GeneratedPosition]].[[Column]]을 _mapping_.[[GeneratedPosition]].[[Column]] + _offsetColumn_으로 설정한다.
              1. _mapping_.[[GeneratedPosition]].[[Line]]을 _mapping_.[[GeneratedPosition]].[[Line]] + _offsetLine_으로 설정한다.
              1. _mapping_을 _offsetMappings_에 append한다.
            1. _sourceMap_.[[Mappings]]을 _sourceMap_.[[Mappings]]와 _offsetMappings_의 list-concatenation으로 설정한다.
            1. _previousOffsetPosition_을 _offsetPosition_으로 설정한다.
            1. _offsetMappings_가 비어 있지 않으면, _previousLastMapping_을 _offsetMappings_의 마지막 요소로 설정한다.
        1. _sourceMap_을 반환한다.
    
Note
구현은 예를 들어 각 section을 별도로 저장하고 이진 검색을 수행하는 방식으로, mapping을 함께 append하지 않고 인덱스 소스 맵 section을 표현하도록 선택할 수 있다.

11 소스 맵 검색

11.1 생성된 코드를 소스 맵에 연결하기

소스 맵 형식은 언어 및 플랫폼에 독립적인 것을 의도하지만, 웹 서버에서 호스팅되는 JavaScript라는 예상 사용 사례에 대해 이를 참조하는 방법을 정의하는 것이 유용하다.

소스 맵을 출력에 연결하는 방법은 두 가지가 가능하다. 첫 번째는 HTTP 헤더를 추가하기 위한 서버 지원이 필요하고, 두 번째는 소스 안의 주석이 필요하다.

소스 맵은 WHATWG URL에서 정의한 URL을 통해 연결된다. 특히 URI에 나타날 수 있는 허용 집합 밖의 문자는 퍼센트 인코딩되어야 하며, data URI일 수도 있다. data URI를 sourcesContent와 함께 사용하면 완전히 자체 포함된 소스 맵을 만들 수 있다.

HTTP sourcemap 헤더는 소스 주석보다 우선하며, 둘 다 존재하면 헤더 URL을 사용하여 소스 맵 파일을 해석해야 한다.

소스 맵 URL을 검색하는 데 사용된 방법과 관계없이, 동일한 절차를 사용하여 이를 해석하며, 그 절차는 다음과 같다.

소스 맵 URL이 절대 URL이 아닌 경우, 이는 생성된 코드소스 origin에 상대적이다. 소스 origin은 다음 경우 중 하나에 의해 결정된다:

  • 생성된 소스가 src 속성을 가진 script 요소와 연관되어 있지 않고, 생성된 코드//# sourceURL 주석이 존재하면, 그 주석을 사용하여 소스 origin을 결정해야 한다.

    Note
    이전에는 이것이 //@ sourceURL였으며, //@ sourceMappingURL와 마찬가지로 둘 다 허용하는 것이 합리적이지만 //#가 선호된다.
  • 생성된 코드가 script 요소와 연관되어 있고 script 요소가 src 속성을 가지면, script 요소의 src 속성이 소스 origin이 된다.
  • 생성된 코드가 script 요소와 연관되어 있고 script 요소가 src 속성을 가지지 않으면, 소스 origin은 페이지의 origin이 된다.
  • 생성된 코드eval() 함수 또는 new Function()을 통해 문자로 평가되는 경우, 소스 origin은 페이지의 origin이 된다.

11.1.1 HTTP 헤더를 통한 연결

파일이 sourcemap 헤더와 함께 HTTP(S)를 통해 제공되는 경우, 헤더의 값은 연결된 소스 맵의 URL이다.

sourcemap: <url>
Note
이 문서의 이전 개정판에서는 헤더 이름으로 x-sourcemap을 권장했다. 이는 이제 폐기 예정이며, 이제는 sourcemap이 기대된다.

11.1.2 인라인 주석을 통한 연결

생성된 코드는 언어 또는 형식에 따라 주석이나 이에 해당하는 구조를 포함해야 하며, 그 이름은 sourceMappingURL이고 소스 맵의 URL을 포함해야 한다. 이 명세는 JavaScript, CSS, WebAssembly에 대해 주석이 어떻게 보여야 하는지를 정의한다. 다른 언어도 유사한 규칙을 따라야 한다.

주어진 언어에 대해 sourceMappingURL 주석을 감지하는 방법은 여러 가지가 있을 수 있으며, 이는 서로 다른 구현이 덜 복잡한 방법을 선택할 수 있도록 하기 위함이다. 모든 추출 방법의 결과가 같으면 생성된 코드는 소스 맵에 명확하게 연결된다.

도구가 소스 맵에 명확하게 연결된 하나 이상의 소스 파일을 소비하고 소스 맵에 연결된 출력 파일을 생성하는 경우, 그 출력 파일도 명확하게 그렇게 해야 한다.

Note

다음 JavaScript 코드는 소스 맵에 연결되지만, 명확하게 그렇게 하지는 않는다:

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

이로부터 소스 맵 URL구문 분석을 통해 추출하면 foo.js.map이 나오지만, 구문 분석 없이 추출하면 null이 나온다.

11.1.2.1 JavaScriptExtractSourceMapURL ( source: a String, ): a String or null

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS.

소스 맵 URL구문 분석을 통해 추출하려면:

#### ECMARKDOWN PARSE FAILED ####
          1. _source_를 ECMA-262의 어휘 문법에 따라 구문 분석하여 얻은 입력 요소의 List를 _tokens_라 한다.
          1. _tokens_의 각 비단말 _token_에 대해 역순으로 다음을 수행한다.
            1. _token_이 |SingleLineComment|, |WhiteSpace| 또는 |LineTerminatorSequence|가 아니면 *null*을 반환한다.
            1. _token_의 내용을 _comment_라 한다.
            1. MatchSourceMapURL(_comment_)을 _sourceMapURL_이라 한다.
            1. _sourceMapURL_이 String이면 _sourceMapURL_을 반환한다.
          1. *null*을 반환한다.
        

소스 맵 URL구문 분석 없이 추출하려면:

#### ECMARKDOWN PARSE FAILED ####
          1. StringSplit(_source_, « *"\u000D\u000A"*, *"\u000A"*, *"\u000D"*, *"\u2028"*, *"\u2029"* »)을 _lines_라 한다.
          1. 참고: 위 문자열 목록은 |LineTerminatorSequence| 생성 규칙과 일치한다.
          1. _lines_의 각 String _lineStr_에 대해 List의 역순으로 다음을 수행한다.
            1. StringToCodePoints(_lineStr_)를 _line_이라 한다.
            1. _position_을 0으로 한다.
            1. _line_의 길이를 _lineLength_라 한다.
            1. _position_ < _lineLength_인 동안 다음을 반복한다.
              1. _line_[_position_]을 _first_라 한다.
              1. _first_가 U+002F (SOLIDUS)이고 _position_ + 1 < _lineLength_이면 다음을 수행한다.
                1. _position_을 _position_ + 1로 설정한다.
                1. _line_[_position_]을 _second_라 한다.
                1. _second_가 U+002F (SOLIDUS)이면 다음을 수행한다.
                  1. _position_을 _position_ + 1로 설정한다.
                  1. _lineStr_에서 _position_부터 _lineLength_까지의 부분 문자열을 _comment_라 한다.
                  1. _comment_에 코드 포인트 U+0022 (QUOTATION MARK), U+0027 (APOSTROPHE) 또는 U+0060 (GRAVE ACCENT) 중 하나가 포함되어 있으면 다음을 수행한다.
                    1. *null*을 반환한다.
                  1. _comment_에 코드 포인트 U+002A (ASTERISK) 바로 뒤에 코드 포인트 U+002F (SOLIDUS)가 포함되어 있으면 다음을 수행한다.
                    1. *null*을 반환한다.
                  1. MatchSourceMapURL(_comment_)을 _sourceMapURL_이라 한다.
                  1. _sourceMapURL_이 String이면 _sourceMapURL_을 반환한다.
                  1. _position_을 _lineLength_로 설정한다.
                1. 그렇지 않으면 다음을 수행한다.
                  1. *null*을 반환한다.
              1. 그렇지 않고 _first_가 ECMAScript |WhiteSpace|이면 다음을 수행한다.
                1. _position_을 _position_ + 1로 설정한다.
              1. 그렇지 않으면 다음을 수행한다.
                1. *null*을 반환한다.
          1. *null*을 반환한다.
        
Note

source를 오류 없이 구문 분석할 수 있고, 그로부터 소스 맵 URL구문 분석 없이 추출한 결과가 null이 아니면, 이를 구문 분석을 통해 추출해도 같은 결과가 나온다.

11.1.2.1.1 MatchSourceMapURL ( comment: a String, ): either none or a String

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
            1. _pattern_을 RegExpCreate(*"^[@#]\\s\*sourceMappingURL=(\\S\*?)\\s\*$"*, *""*)로 둔다.
            1. _match_를 RegExpExec(_pattern_, _comment_)로 둔다.
            1. _match_가 *null*이 아니면, Get(_match_, *"1"*)을 반환한다.
            1. ~none~을 반환한다.
          
Note
이 주석의 접두사는 처음에는 //@였지만, 이는 Internet Explorer의 Conditional Compilation과 충돌하여 //#로 변경되었다.

소스 맵 생성기는 //#만 내보내야 하지만, 소스 맵 소비자는 //@//#를 모두 허용해야 한다.

11.1.2.2 CSSExtractSourceMapURL ( source: a String, ): a String or null

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS.

CSS에서 소스 맵 URL을 추출하는 것은 JavaScript와 유사하지만, CSS는 /* ... */ 스타일 주석만 지원한다는 예외가 있다.

11.1.2.3 WebAssemblyExtractSourceMapURL ( bytes: a Data Block, ): a String or null

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS.

#### ECMARKDOWN PARSE FAILED ####
        1. _module_을 module_decode(_bytes_)로 둔다.
        1. _module_이 WebAssembly error이면, *null*을 반환한다.
        1. _module_의 각 custom section _customSection_에 대해 다음을 수행한다.
          1. _name_을 _customSection_의 `name`으로 둔다.
          1. CodePointsToString(_name_)이 *"sourceMappingURL"*이면,
            1. _value_를 _customSection_의 `bytes`로 둔다.
            1. CodePointsToString(_value_)를 반환한다.
        1. *null*을 반환한다.
      

WebAssembly는 텍스트 형식이 아니며 주석을 지원하지 않으므로, 하나의 명확한 추출 방법을 지원한다. URL은 WebAssembly 이름으로 인코딩되며, custom section의 콘텐츠로 배치된다. WebAssembly 코드를 생성하는 도구가 sourceMappingURL 이름을 가진 두 개 이상의 custom section을 생성하는 것은 유효하지 않다.

11.2 소스 맵 가져오기

11.2.1 FetchSourceMap ( url: an URL, ): a Promise

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
        1. _promiseCapability_를 NewPromiseCapability(%Promise%)로 둔다.
        1. _request_를 요청 URL이 _url_인 새 request로 둔다.
        1. _processResponseConsumeBody_를 _promiseCapability_와 _url_을 캡처하고 호출될 때 다음 단계를 수행하는, 매개변수 (_response_, _bodyBytes_)를 가진 새 Abstract Closure로 둔다.
          1. _bodyBytes_가 *null* 또는 ~failure~이면,
            1. Call(_promiseCapability_.[[Reject]], *undefined*, « 새 *TypeError* »)를 수행한다.
            1. 반환한다.
          1. _url_의 scheme이 HTTP(S) scheme이고 바이트 시퀀스 \``)]}'`\`가 _bodyBytes_의 byte-sequence-prefix이면,
            1. _bodyBytes_의 byte-sequence-length가 0이 아니고 _bodyBytes_[0]이 HTTP newline byte가 아닌 동안 반복한다.
              1. _bodyBytes_에서 0번째 요소를 제거한다.
          1. _bodyString_을 _bodyBytes_의 UTF-8 decode의 Completion으로 둔다.
          1. IfAbruptRejectPromise(_bodyString_, _promiseCapability_).
          1. _jsonValue_를 ParseJSON(_bodyString_)의 Completion으로 둔다.
          1. IfAbruptRejectPromise(_jsonValue_, _promiseCapability_).
          1. Call(_promiseCapability_.[[Resolve]], *undefined*, « _jsonValue_ »)를 수행한다.
        1. processResponseConsumeBody를 _processResponseConsumeBody_로 설정하여 _request_를 fetch 수행한다.
        1. _promiseCapability_.[[Promise]]를 반환한다.
      
Note

역사적 이유로, HTTP(S)를 통해 소스 맵을 전달할 때 서버는 문자 )]}'로 시작하는 줄을 소스 맵 앞에 붙일 수 있다.

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

이는 다음과 같이 해석된다

{"version": 3, ...}

12 소스 맵 레코드에 대한 연산

소스 맵을 디코딩한 후, 소스 맵 소비자는 결과로 나온 Decoded Source Map Records를 사용하여 디버깅 또는 기타 사용 사례를 위한 위치 정보를 조회할 수 있다. 이 절은 소스 맵 소비자가 지원할 수 있는 일반적인 연산의 동작을 설명한다.

GetOriginalPositions 연산은 생성된 코드의 위치에 대응하는 원본 소스의 위치를 질의하는 데 사용할 수 있다. 예를 들어, 디버거에서 사용자의 마우스 클릭을 기반으로 생성된 코드에서 원본 소스로 이동하는 데 사용할 수 있다.

12.1 GetOriginalPositions ( sourceMapRecord: a Decoded Source Map Record, generatedPosition: a Position Record, ): a List of Original Position Records

The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:

#### ECMARKDOWN PARSE FAILED ####
      1. _mappings_를 _sourceMapRecord_.[[Mappings]]로 둔다.
      1. _last_를 *null*로 둔다.
      1. _originalPositions_를 새 빈 List로 둔다.
      1. _mappings_의 각 요소 _mapping_에 대해 역 List 순서로 다음을 수행한다.
        1. _last_가 *null*이면,
          1. ComparePositions(_mapping_.[[GeneratedPosition]], _generatedPosition_)를 수행한 결과가 ~lesser~ 또는 ~equal~이면,
            1. _last_를 _mapping_으로 설정한다.
      1. _last_가 *null*이 아니면,
        1. _mappings_의 각 요소 _mapping_에 대해 다음을 수행한다.
          1. ComparePositions(_last_.[[GeneratedPosition]], _mapping_.[[GeneratedPosition]])를 수행한 결과가 ~equal~이면,
            1. _mapping_.[[OriginalPosition]]을 _originalPositions_에 append한다.
      1. _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 → 축소된 JavaScript를 컴파일하여, 최종 소스 맵이 만들어지기 전에 여러 번의 변환이 발생하는 일이 점점 더 일반화되고 있다. 이 문제는 두 가지 방법 중 하나로 처리할 수 있다. 쉽지만 손실이 있는 방법은 디버깅 목적에서 중간 단계를 무시하는 것으로, 변환에서 나온 소스 위치 정보는 무시되거나(중간 변환이 “Original Source”로 간주됨) 소스 위치 정보가 그대로 전달된다(중간 변환은 숨겨짐). 더 완전한 방법은 여러 수준의 매핑을 지원하는 것이다. Original Source도 소스 맵 참조를 가지고 있다면, 사용자에게 그것도 사용할 수 있는 선택권을 준다.

그러나 JavaScript 외의 어떤 것에서 “source map reference”가 어떻게 보이는지는 명확하지 않다. 더 구체적으로는, 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. Variable-length quantity, Wikipedia, available at <https://en.wikipedia.org/wiki/Variable-length_quantity>

Annex E (informative) 콜로폰

이 명세는 GitHub에서 Ecmarkup이라는 일반 텍스트 소스 형식으로 작성된다. Ecmarkup은 일반 텍스트로 ECMAScript 명세를 작성하고, 명세를 이 문서의 편집 규칙을 따르는 완전한 기능의 HTML 렌더링으로 처리하기 위한 프레임워크와 도구 모음을 제공하는 HTML 및 Markdown 방언이다. Ecmarkup은 구문 정의를 위한 Grammarkdown과 알고리즘 단계를 작성하기 위한 Ecmarkdown을 포함하여 여러 다른 형식과 기술 위에 구축되고 통합된다. 이 명세의 PDF 렌더링은 HTML 렌더링을 PDF로 인쇄하여 생성된다.

이 명세의 초판은 HTML과 Markdown 기반의 다른 일반 텍스트 소스 형식인 Bikeshed를 사용하여 작성되었다.

이 문서의 표준화 이전 버전은 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.