?ue/p1-90`https://tc39.es/ecma426/의 문서는 가장 정확하고 최신인 소스 맵 명세이다. 이 문서는 가장 최근에 공개된 스냅샷의 내용과 다음 스냅샷에 포함될 모든 변경 사항을 포함한다.
이 명세는 GitHub에서 개발된다. 이 명세의 개발에 기여하는 방법에는 여러 가지가 있다:
이 문서가 어떻게 생성되는지에 대한 자세한 내용은
이 Ecma 표준은 트랜스파일된 소스 코드를
소스 맵 형식은 다음 목표를 가진다:
소스 맵 형식은 더 이상 버전 번호를 가지지 않으며, 대신 항상 “3”으로 하드코딩된다.
2023-2024년에 소스 맵 형식은 많은 사람의 중요한 기여와 함께 더 정밀한 Ecma 표준으로 개발되었다. 소스 맵 형식에 대한 추가 반복 작업은 TC39-TG4에서 이루어질 것으로 예상된다.
Asumu Takikawa, Nicolò Ribaudo, Jon Kuperman
ECMA-426, 제1판, 프로젝트 편집자
이 표준은 JavaScript, WebAssembly, CSS로 컴파일된 코드의 디버깅 경험을 개선하기 위해 여러 유형의 개발자 도구에서 사용되는 소스 맵 형식을 정의한다.
준수하는 소스 맵 문서는 이 명세에 자세히 설명된 구조를 따르는 JSON 문서이다.
준수하는 소스 맵 생성기는 준수하는 소스 맵 문서인 문서를 생성해야 하며, 이 명세의 알고리즘으로 디코딩할 때 어떤 오류도 보고하지 않아야 한다(선택 사항으로 명시된 오류까지 포함).
준수하는 소스 맵 소비자는 소스 맵 문서를 검색(해당하는 경우)하고 디코딩하기 위해 이 명세에 지정된 알고리즘을 구현해야 한다. 명세에서 알고리즘이
다음 문서는 그 내용의 일부 또는 전부가 이 문서의 요구사항을 구성하도록 본문에서 참조된다. 날짜가 있는 참조의 경우 인용된 판만 적용된다. 날짜가 없는 참조의 경우 참조된 문서의 최신판(모든 수정 포함)이 적용된다.
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/
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
https://fetch.spec.whatwg.org/
WHATWG Infra.
https://infra.spec.whatwg.org/
WHATWG
https://url.spec.whatwg.org/
이 명세는 이 절에서 정의된 확장을 포함하여, ECMA-262(표기 규칙)에서 정의한 것과 동일한 표기 규칙을 따른다.
이 명세에 선언된 모든 추상 연산은 알고리즘의 선언된 반환 유형을 포함하는 정상 완료 또는 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.
완료 레코드를 반환하는 추상 연산에 대한 모든 호출은 명시적인 ? 완료 레코드 언래핑 약식으로 감싸졌다고 암시적으로 가정한다. 예를 들면 다음과 같다:
1. _result_를 GetTheAnswer(_value_)로 둔다.
1. _second_를 Completion(GetTheAnswer(_value_))로 둔다.
이는 다음과 동등하다:
1. _result_를 ? GetTheAnswer(_value_)로 둔다.
1. _second_를 Completion(GetTheAnswer(_value_))로 둔다.
알고리즘이 오류를 선택적으로 보고해야 할 때마다, 구현은 다음 동작 중 하나를 선택할 수 있다:
구현은 서로 다른 선택적 오류에 대해 서로 다른 동작을 선택할 수 있다.
이 명세는 다음 주의 사항을 포함하여, ECMA-262(문법 표기)에서 정의한 것과 동일한 문법 표기 규칙을 따른다:
이 문서의 목적상, 다음 용어와 정의가 적용된다.
컴파일러 또는 트랜스파일러에 의해
컴파일러 또는 트랜스파일러를 거치지 않은 소스 코드.
LATIN CAPITAL LETTER A)가 1 코드 단위로 측정되고, “🔥”(FIRE)가 2 코드 단위로 측정됨을 의미한다. 다른 콘텐츠 유형의 소스 맵은 이와 다를 수 있다.base64 VLQ는
base64 VLQ는 다음 어휘 문법을 따른다:
The
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_를 반환한다.
The
1. _value_를 |VlqDigitList|의 VLQUnsignedValue로 둔다.
1. _value_가 ≥ 232이면, 오류를 throw한다.
1. _value_를 반환한다.
1. _left_를 |ContinuationDigit|의 VLQUnsignedValue로 둔다.
1. _right_를 |VlqDigitList|의 VLQUnsignedValue로 둔다.
1. _left_ + _right_ × 25를 반환한다.
1. _digit_을 이 production과 일치한 문자로 둔다.
1. _value_를 IETF RFC 4648에서 정의한 base64 인코딩에 따라 _digit_에 대응하는 정수로 둔다.
1. Assert: _value_ < 32.
1. _value_를 반환한다.
1. _digit_을 이 production과 일치한 문자로 둔다.
1. _value_를 IETF RFC 4648에서 정의한 base64 인코딩에 따라 _digit_에 대응하는 정수로 둔다.
1. Assert: 32 ≤ _value_ < 64.
1. _value_ - 32를 반환한다.
이 명세의 알고리즘은 ECMA-262 내부 구조 위에서 정의되지만, JavaScript가 아닌 플랫폼에서도 쉽게 구현할 수 있도록 의도되었다. 이 절은
JSON 값은
JSON 객체는 그 각 프로퍼티가 다음을 만족하는 Object이다:
JSON 배열은 다음을 만족하는
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
1. _result_를 Call(%JSON.parse% , *null*, « _string_ »)로 둔다. 1. Assert: _result_는 JSON 값이다. 1. _result_를 반환한다.
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
1. _object_가 키 _key_를 가진 자체 프로퍼티를 가지지 않으면, ~missing~을 반환한다.
1. _prop_을 키가 _key_인 _object_의 자체 프로퍼티로 둔다.
1. _prop_의 [[Value]] 속성을 반환한다.
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
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_를 반환한다.
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
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_를 반환한다.
Position Record는 음수가 아닌 줄 번호와 음수가 아닌
| 필드 이름 | 값 타입 |
|---|---|
| [[Line]] | 음수가 아닌 정수 Number |
| [[Column]] | 음수가 아닌 정수 Number |
Original Position Record는
| 필드 이름 | 값 타입 |
|---|---|
| [[Source]] | |
| [[Line]] | 음수가 아닌 정수 Number |
| [[Column]] | 음수가 아닌 정수 Number |
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
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~을 반환한다.
소스 맵은 다음 구조를 가진 최상위
{
"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]
}
version 필드는 항상 정수인 숫자 3이어야 한다. 이 필드가 다른 값을 가지면 소스 맵은 거부될 수 있다.file 필드는 이 소스 맵과 연관된 sourceRoot 필드는 서버에서 소스 파일을 재배치하거나 sources 항목의 반복 값을 제거하는 데 사용되는 선택적 소스 루트 문자sources 필드는 sourcesContent 필드는 소스를 호스팅할 수 없을 때 사용되는 소스 콘텐츠(즉 names 필드는 mappings 필드는 인코딩된 매핑 데이터를 가진 문자ignoreList 필드는 프레임워크 코드 또는 번들러가 ignoreList가 없는 경우 폐기 예정인 x_google_ignoreList 필드도 사용할 수 있다.Decoded Source Map Record는 다음 필드를 가진다:
| 필드 이름 | 값 타입 |
|---|---|
| [[File]] | String 또는 |
| [[Sources]] | |
| [[Mappings]] |
Decoded Source Record는 다음 필드를 가진다:
| 필드 이름 | 값 타입 |
|---|---|
| [[URL]] | |
| [[Content]] | String 또는 |
| [[Ignored]] | Boolean |
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
1. _json_을 ParseJSON(_string_)으로 둔다.
1. _json_이 JSON 객체가 아니면, 오류를 throw한다.
1. JSONObjectGet(_json_, *"sections"*)가 ~missing~이 아니면,
1. DecodeIndexSourceMap(_json_, _baseURL_)을 반환한다.
1. DecodeSourceMap(_json_, _baseURL_)을 반환한다.
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
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_ }를 반환한다.
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
1. _value_를 JSONObjectGet(_object_, _key_)로 둔다.
1. _value_가 String이면, _value_를 반환한다.
1. _value_가 ~missing~이 아니면, 오류를 선택적으로 보고한다.
1. *null*을 반환한다.
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
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_를 반환한다.
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
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_를 반환한다.
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
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_를 반환한다.
;)으로 구분된다,)로 구분된다각 segment의 필드는 다음과 같다:
;) 뒤의 첫 번째 segment라면, 이 필드는 전체 Decoded Mapping Record는 다음 필드를 가진다:
| 필드 이름 | 값 타입 |
|---|---|
| [[GeneratedPosition]] | |
| [[OriginalPosition]] | |
| [[Name]] | String 또는 |
mappings String은 다음 문법을 따라야 한다:
Decode Mapping State Record는 다음 필드를 가진다:
| 필드 이름 | 값 타입 |
|---|---|
| [[GeneratedLine]] | 음수가 아닌 정수 |
| [[GeneratedColumn]] | 음수가 아닌 정수 |
| [[SourceIndex]] | 음수가 아닌 정수 |
| [[OriginalLine]] | 음수가 아닌 정수 |
| [[OriginalColumn]] | 음수가 아닌 정수 |
| [[NameIndex]] | 음수가 아닌 정수 |
The
1. |Line|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
1. _state_.[[GeneratedLine]]을 _state_.[[GeneratedLine]] + 1로 설정한다.
1. _state_.[[GeneratedColumn]]을 0으로 설정한다.
1. |LineList|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
1. 반환한다.
1. |Mapping|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
1. |MappingList|의 DecodeMappingsField를 _state_, _mappings_, _names_, _sources_ 인수로 수행한다.
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한다.
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한다.
1. _relativeColumn_을 |Vlq|의 VLQSignedValue로 둔다.
1. _state_.[[GeneratedColumn]]을 _state_.[[GeneratedColumn]] + _relativeColumn_으로 설정한다.
1. _relativeSourceIndex_를 |Vlq|의 VLQSignedValue로 둔다.
1. _state_.[[SourceIndex]]를 _state_.[[SourceIndex]] + _relativeSourceIndex_로 설정한다.
1. _relativeLine_을 |Vlq|의 VLQSignedValue로 둔다.
1. _state_.[[OriginalLine]]을 _state_.[[OriginalLine]] + _relativeLine_으로 설정한다.
1. _relativeColumn_을 |Vlq|의 VLQSignedValue로 둔다.
1. _state_.[[OriginalColumn]]을 _state_.[[OriginalColumn]] + _relativeColumn_으로 설정한다.
1. _relativeName_을 |Vlq|의 VLQSignedValue로 둔다.
1. _state_.[[NameIndex]]를 _state_.[[NameIndex]] + _relativeName_으로 설정한다.
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
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_를 반환한다.
다음과 같은 경우, 소스 맵 생성기는 JavaScript 토큰에 대해 [[Name]] 필드를 가진
그런 경우
다음
이
(.
소스 맵 생성기는
=> 토큰.
(.
소스 맵 생성기는 이전 경우와의 일관성을 위해 => 토큰에 추가로 named mapping을 내보낼 수도 있다.
소스 맵 생성기는 여는 괄호 (에 추가로 named mapping을 내보낼 수도 있다.
소스 맵 생성기는
sourceRoot를 앞에 붙인 후 sources가 절대 src 속성을 해석하는 것과 같다).
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
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_를 반환한다.
소스 맵 소비자는 추가 기능을 이 형식에 추가해도 기존 사용자를 깨뜨리지 않도록, 인식하지 못하는 추가 프로퍼티로 인해 소스 맵을 거부하지 말고 이를 무시해야 한다.
{
"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 및
sections 필드는 다음 필드를 가진 객체의 배
offset 필드는 line과 column 두 필드를 가진 객체이며, 참조된 소스 맵이 나타내는 map 필드는 삽입된 완전한 소스 맵 객체이다. 삽입된 맵은 포함하는 인덱스 맵으로부터 어떤 값도 상속하지 않는다.sections는 시작 위치로 정렬되어야 하며, 표현되는 sections는 겹치지 않아야 한다.
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
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_을 반환한다.
소스 맵 형식은 언어 및 플랫폼에 독립적인 것을 의도하지만, 웹 서버에서 호스팅되는 JavaScript라는 예상 사용 사례에 대해 이를 참조하는 방법을 정의하는 것이 유용하다.
소스 맵을 출력에 연결하는 방법은 두 가지가 가능하다. 첫 번째는 HTTP 헤더를 추가하기 위한 서버 지원이 필요하고, 두 번째는 소스 안의 주석이 필요하다.
소스 맵은
HTTP sourcemap 헤더는 소스 주석보다 우선하며, 둘 다 존재하면 헤더
생성된 소스가 src 속성을 가진 script 요소와 연관되어 있지 않고, //# sourceURL 주석이 존재하면, 그 주석을 사용하여
//@ sourceURL였으며, //@ sourceMappingURL와 마찬가지로 둘 다 허용하는 것이 합리적이지만 //#가 선호된다.
src 속성을 가지면, script 요소의 src 속성이 src 속성을 가지지 않으면, eval() 함수 또는 new Function()을 통해 문자파일이 sourcemap 헤더와 함께 HTTP(S)를 통해 제공되는 경우, 헤더의 값은 연결된 소스 맵의
sourcemap: <url>
x-sourcemap을 권장했다. 이는 이제 폐기 예정이며, 이제는 sourcemap이 기대된다.
sourceMappingURL이고 소스 맵의
주어진 언어에 대해 sourceMappingURL 주석을 감지하는 방법은 여러 가지가 있을 수 있으며, 이는 서로 다른 구현이 덜 복잡한 방법을 선택할 수 있도록 하기 위함이다. 모든 추출 방법의 결과가 같으면
도구가 소스 맵에 명확하게 연결된 하나 이상의 소스 파일을 소비하고 소스 맵에 연결된 출력 파일을 생성하는 경우, 그 출력 파일도
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS.
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*을 반환한다.
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*을 반환한다.
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
1. _pattern_을 RegExpCreate(*"^[@#]\\s\*sourceMappingURL=(\\S\*?)\\s\*$"*, *""*)로 둔다.
1. _match_를 RegExpExec(_pattern_, _comment_)로 둔다.
1. _match_가 *null*이 아니면, Get(_match_, *"1"*)을 반환한다.
1. ~none~을 반환한다.
//@였지만, 이는 Internet Explorer의 Conditional Compilation과 충돌하여 //#로 변경되었다.소스 맵 생성기는 //#만 내보내야 하지만, 소스 맵 소비자는 //@와 //#를 모두 허용해야 한다.
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS.
CSS에서 /* ... */ 스타일 주석만 지원한다는 예외가 있다.
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS.
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는 텍스트 형식이 아니며 주석을 지원하지 않으므로, 하나의 명확한 추출 방법을 지원한다. sourceMappingURL 이름을 가진 두 개 이상의
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
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]]를 반환한다.
역사적 이유로, HTTP(S)를 통해 소스 맵을 전달할 때 서버는 문자)]}'로 시작하는 줄을 소스 맵 앞에 붙일 수 있다.
)]}'garbage here
{"version": 3, ...}
이는 다음과 같이 해석된다
{"version": 3, ...}
소스 맵을 디코딩한 후, 소스 맵 소비자는 결과로 나온
GetOriginalPositions 연산은
The abstract operation UNKNOWN takes UNPARSEABLE ARGUMENTS. It performs the following steps when called:
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_를 반환한다.
소스 맵으로 작업하거나 이를 생성할 때 다음 규칙을 따라야 한다.
일반적으로 소스 맵은 생성된 파일과 같은 이름을 가지지만 .map 확장자를 가진다. 예를 들어 page.js에 대해서는 page.js.map이라는 이름의 소스 맵이 생성된다.
eval된 코드와 함께 소스 맵을 사용할 때 지원해야 하는 기존 규칙이 있으며, 이는 다음 형식을 가진다:
//# sourceURL=foo.js
이는
소스 언어에 대한 지식 없는 스택 추적 매핑은 이 문서에서
도구가 어떤 DSL(템플릿)에서 소스를 생성하거나 TypeScript → JavaScript → 축소된 JavaScript를 컴파일하여, 최종 소스 맵이 만들어지기 전에 여러 번의 변환이 발생하는 일이 점점 더 일반화되고 있다. 이 문제는 두 가지 방법 중 하나로 처리할 수 있다. 쉽지만 손실이 있는 방법은 디버깅 목적에서 중간 단계를 무시하는 것으로, 변환에서 나온 소스 위치 정보는 무시되거나(중간 변환이 “Original Source”로 간주됨) 소스 위치 정보가 그대로 전달된다(중간 변환은 숨겨짐). 더 완전한 방법은 여러 수준의 매핑을 지원하는 것이다. Original Source도 소스 맵 참조를 가지고 있다면, 사용자에게 그것도 사용할 수 있는 선택권을 준다.
그러나 JavaScript 외의 어떤 것에서 “source map reference”가 어떻게 보이는지는 명확하지 않다. 더 구체적으로는, JavaScript 스타일의 한 줄 주석을 지원하지 않는 언어에서 소스 맵 참조가 어떻게 보이는지가 명확하지 않다.
이 절은 이 문서에서 사용되는 용어와 알고리즘 중 ECMA-262가 아닌 외부 명세에서 정의된 모든 것을 나
이 명세는 GitHub에서 Ecmarkup이라는 일반 텍스트 소스 형식으로 작성된다. Ecmarkup은 일반 텍스트로 ECMAScript 명세를 작성하고, 명세를 이 문서의 편집 규칙을 따르는 완전한 기능의 HTML 렌더링으로 처리하기 위한 프레임워크와 도구 모음을 제공하는 HTML 및 Markdown 방언이다. Ecmarkup은 구문 정의를 위한 Grammarkdown과 알고리즘 단계를 작성하기 위한 Ecmarkdown을 포함하여 여러 다른 형식과 기술 위에 구축되고 통합된다. 이 명세의 PDF 렌더링은 HTML 렌더링을 PDF로 인쇄하여 생성된다.
이 명세의 초판은 HTML과 Markdown 기반의 다른 일반 텍스트 소스 형식인 Bikeshed를 사용하여 작성되었다.
이 문서의 표준화 이전 버전은 Google Docs를 사용하여 작성되었다.
Ecma International
Rue du Rhone 114
CH-1204 Geneva
Tel: +41 22 849 6000
Fax: +41 22 849 6001
Web: https://ecma-international.org/
COPYRIGHT NOTICE
© 2026 Ecma International
By obtaining and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions.
This document may be copied, published and distributed to others, and certain derivative works of it may be prepared, copied, published, and distributed, in whole or in part, provided that the above copyright notice and this Copyright License and Disclaimer are included on all such copies and derivative works. The only derivative works that are permissible under this Copyright License and Disclaimer are:
(i) works which incorporate all or portion of this document for the purpose of providing commentary or explanation (such as an annotated version of the document),
(ii) works which incorporate all or portion of this document for the purpose of incorporating features that provide accessibility,
(iii) translations of this document into languages other than English and into different formats and
(iv) works by making use of this specification in standard conformant products by implementing (e.g. by copy and paste wholly or partly) the functionality therein.
However, the content of this document itself may not be modified in any way, including by removing the copyright notice or references to Ecma International, except as required to translate it into languages other than English or into a different format.
The official version of an Ecma International document is the English language version on the Ecma International website. In the event of discrepancies between a translated version and the official version, the official version shall govern.
The limited permissions granted above are perpetual and will not be revoked by Ecma International or its successors or assigns.
This document and the information contained herein is provided on an “AS IS” basis and ECMA INTERNATIONAL DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
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:
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.