이 Ecma 표준은 트랜스파일된 소스코드를 원본 소스코드로 맵핑하기 위해 사용되는 소스맵 형식을 정의합니다.
소스맵 형식의 주요 목표는 다음과 같습니다:
양방향 매핑을 통해 소스 수준 디버깅 지원
서버 측 스택 추적 복원 지원
원본 소스 맵 형식(v1)은 최적화된 JavaScript 코드의 소스 수준 디버깅을 위해 Closure Inspector에서 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 참고 문헌
다음 문서들은 이 문서에서 일부 또는 전체 내용이 요구사항을 구성하는 방식으로 참조됩니다. 날짜가 명시된 경우 해당 판만 적용됩니다. 날짜가 없으면, 참조된 문서의 최신 판(개정 포함)을
적용합니다.
생성된 코드의 한 줄 내에서 0부터 시작하는
인덱스 오프셋. JavaScript 및 CSS 소스맵에서는 UTF-16 코드 유닛 수로, WebAssembly 소스맵에서는 바이너리 콘텐츠의 바이트 인덱스(단일 줄로
표현됨)로 계산됨.
참고
즉, "A"(LATIN CAPITAL LETTER A)는 코드 유닛 1로 계산되고,
"🔥"(FIRE)는 코드 유닛 2로 계산됩니다. 다른 콘텐츠 타입의 소스맵에서는 이 규칙이 다를 수 있습니다.
6 base64 VLQ
base64 VLQ는 base64로 인코딩된 가변 길이 정수로, 가장 큰 비트(6번째 비트)가 연속
비트로 사용되며, "숫자"들은 문자열로 최하위부터 순서대로 인코딩되고, 첫 숫자의 최하위 비트가 부호 비트로 사용됩니다.
노트 1
base64 VLQ 인코딩으로 표현할 수 있는 값은 32비트까지만 제한되며, 더 큰 값이 필요한 경우가 있을 때 확장될 수 있습니다. 즉, 32비트를 초과하는 값은 유효하지 않으며
구현체는 이를 거부할 수 있습니다. 부호 비트는 제한에 포함되지만 연속 비트는 포함되지 않습니다.
노트 2
문자열 "iB"는 두 자리의 base64 VLQ를 의미합니다. 첫 자리 "i"는 0b100010 비트 패턴을
인코딩하며, 연속 비트 1(VLQ가 계속됨), 부호 비트 0(음수가 아님), 값 비트 0b0001을 가집니다.
두 번째 자리 B는 0b000001을 인코딩하며, 연속 비트 0, 부호 비트 없음, 값 비트
0b00001을 가집니다. 이 VLQ 문자열을 디코딩하면 숫자 17이 됩니다.
노트 3
문자열 "V"는 한 자리의 base64 VLQ를 의미합니다. "V"는 0b010101 비트 패턴을 인코딩하며,
연속 비트 0(계속 없음), 부호 비트 1(음수), 값 비트 0b1010을 가집니다. 이 VLQ 문자열을
디코딩하면 숫자 -10이 됩니다.
이 추상 연산은 ECMA-262에서 직접 공개되는 작업 중에 있습니다. 관련 논의는 tc39/ecma262#3540에서 볼 수 있습니다.
7.2 JSONObjectGet ( object, key )
추상 연산 JSONObjectGet은 object(JSON 객체)와 key(문자열)를 받아 JSON 값 또는
missing을 반환합니다. object에서 지정된 key에 대응하는 값을 반환합니다. 호출 시
다음 단계를 수행합니다:
object에 key로 된 자체 프로퍼티가 없다면, missing을 반환한다.
prop에 object의 key에 해당하는 자체 프로퍼티를 할당한다.
prop의 [[Value]] 속성을 반환한다.
7.3 JSONArrayIterate ( array )
추상 연산 JSONArrayIterate는 array(JSON 배열)를 받아 리스트(List)
형태의 JSON
값들을 반환합니다. 이는 "For each" 알고리즘 등에서 반복할 수 있도록 array 내의 모든 요소를 포함한
리스트를 만듭니다. 호출 시 다음 단계를 수행합니다:
추상 연산 StringSplit은 string(문자열)과 separators(문자열 리스트)를 받아, 리스트
형식의 문자열 목록을 반환합니다. 문자열을 separators 요소 중 하나로 분리된 하위 문자열로 나누며, 여러 구분자가 동시에 일치하는 경우
separators에서 먼저 등장하는 구분자가 우선 적용됩니다. 다음 단계로 동작합니다:
추상 연산 ComparePositions는 인수 first(위치 레코드 또는 원본 위치 레코드)와
second(위치 레코드 또는 원본 위치 레코드)를 받아
lesser, equal, greater를 반환합니다.
first가 second보다 앞에 있으면 lesser, 같으면
equal, 뒤에 있으면 greater를 반환합니다. 원본 위치 레코드의 [[Source]] 필드는 비교 시 무시됩니다. 호출 시 다음 단계를 수행합니다:
version 필드는 항상 정수 3이어야 합니다. 만약 값이 다를 경우 소스맵이 거부될 수 있습니다.
file 필드는 이 소스맵이 연결되는 생성된 코드의 선택적 이름입니다.
URL이거나, 상대 경로 혹은 단순 파일명일 수 있으며, 소스맵
생성기는 활용 환경에 맞는 해석을 할 수 있습니다.
sourceRoot 필드는 서버에서 소스파일 경로를 재지정하거나
sources 항목 내 반복값을 제거할 때 쓰는 선택적 소스 루트 문자열입니다. 이 값은 sources 필드 각 항목 앞에 붙습니다.
sources 필드는 mappings 필드에서 사용하는 원본 소스 목록입니다. 각 항목은 (상대일 수도 있는) URL 문자열이거나, 소스 이름을 알 수 없을 경우
null입니다.
sourcesContent 필드는 (예를 들어 원본 소스)를, 소스 호스팅이 불가할 때
사용하는 선택적 콘텐츠 문자열 목록입니다. sources 필드와 동일한 순서이며,
일부 원본 소스는 이름으로
조회하여야 하기에 null일 수 있습니다.
names 필드는 mappings 필드에서 사용 가능한 선택적 심볼 이름 목록입니다.
mappings 필드는 인코딩된 매핑 데이터가 담긴 문자열입니다
(9.2 참고).
ignoreList 필드는 프레임워크 코드, 번들러 등과 같은 서드파티
코드로 간주되는 파일의 인덱스 목록(선택적)입니다. 이 필드를 통해 개발자 도구는 사용자가 보고 싶지 않은 코드나 디버깅 시 넘길 코드들을 미리 걸러낼 수 있습니다.
sources 필드의 인덱스를 참조해서 소스맵상의 모든 서드파티 소스 인덱스를
나열하며, 일부 브라우저는 ignoreList가 없을 경우 이전 필드인 x_google_ignoreList도 사용할 수 있습니다.
9.1 소스맵 디코딩
디코딩된 소스맵
레코드는 다음 필드들을 가집니다:
표 3: 디코딩된 소스맵
레코드의 필드
필드 이름
값 타입
[[File]]
문자열 또는 null
[[Sources]]
List의
디코딩된 소스 레코드
[[Mappings]]
List의
디코딩된 매핑 레코드
디코딩된 소스 레코드는 다음
필드들을 가집니다:
표 4: 디코딩된 소스 레코드의 필드
필드 이름
값 타입
[[URL]]
URL 또는
null
[[Content]]
문자열 또는 null
[[Ignored]]
Boolean
9.1.1 ParseSourceMap ( string, baseURL )
추상 연산 ParseSourceMap은 인수 string(문자열)과 baseURL(URL)을 받아 디코딩된 소스맵 레코드를 반환합니다. 호출 시 다음 단계들을
수행합니다:
json을 ParseJSON(string)으로 한다.
json이 JSON 객체가 아니면
오류를 발생시킨다.
JSONObjectGet(json,
"sections")이 missing이 아니면,
DecodeIndexSourceMap(json,
baseURL)을 반환한다.
DecodeSourceMap(json, baseURL)을 반환한다.
9.1.2 DecodeSourceMap ( json, baseURL )
추상 연산 DecodeSourceMap은 json (JSON 객체)와 baseURL (URL)을
인자로 받고 디코딩된 소스 맵 레코드를 반환한다. 호출 시 다음 단계를 수행한다:
column의 0부터 시작하는 생성 코드의 줄 번호. 해당
세그먼트가 첫 번째 필드이거나, 새로운 생성 코드 줄(;) 뒤의 첫번째 세그먼트인 경우, 이 필드는 전체 base64 VLQ 값을
갖습니다. 그렇지 않은 경우, 이 필드는 이전 필드의 발생과 상대적인 base64 VLQ 값을 갖습니다. 이 필드는 아래의 후속 필드들과 달리 이전 값이
각 생성된 라인마다 초기화됨에 유의하세요.
존재하는 경우, 소스 리스트의 0부터 시작하는 인덱스입니다. 이 필드는 base64 VLQ로 이전의 필드 발생과 상대값을 표시하는데, 이 필드가 처음 발생하면
전체값을 가집니다.
존재하는 경우, 원본 소스에서의 0부터 시작하는 줄
번호입니다. 이 필드는 또한 base64
VLQ로 이전 발생과 상대값을 갖으며, 처음이면 전체값이 됩니다. source 필드가 있으면 반드시 존재해야 합니다.
존재하는 경우, column의 0부터 시작하는 원본 소스 줄 번호. 이
필드는 base64
VLQ로 이전 발생과 상대값을 표시하며, 처음이면 전체값을 갖습니다. source 필드가 있으면 반드시 존재해야 합니다.
존재하는 경우, 해당 세그먼트와 연결된 names 리스트의 0부터 시작하는 인덱스입니다. 이 필드는 base64
VLQ로 이전 발생과 상대값을 표시하며, 처음이면 전체값입니다.
참고 1
이 인코딩의 목적은 소스 맵의 크기를 줄이는 것입니다. VLQ 인코딩은 Google Calendar를 이용하여 테스트한 결과,
Source Map
Revision 2 Proposal 에 비해 50%가량 소스맵을 줄였습니다.
참고 2
필드가 1개인 세그먼트는 생성 코드가 매핑되지
않은 경우(즉, 원본 소스 코드가 없어서 컴파일러에 의해
생성된 코드 등) 나타내기 위해 사용됩니다. 필드가 4개인 세그먼트는 이름이 없는 매핑된 코드를 나타내고, 필드가 5개인 세그먼트는 매핑된 이름이 있는 매핑된 코드를
나타냅니다.
참고 3
file 오프셋 사용도 고려되었으나, 원본 파일과의 불일치(플랫폼별 줄 끝 처리
차이 등)를 방지하기 위해 line/column 데이터를 사용하는 방식을 채택했습니다.
originalPosition을 새로운 Original Position
Record { [[Source]]:
sources[state.[[SourceIndex]]], [[Line]]:
state.[[OriginalLine]], [[Column]]: state.[[OriginalColumn]]}로 설정합니다.
이때 매핑 항목의 [[Name]]
값은 원본 소스 언어 구조의 이름이 되어야
합니다. 매핑 중에서 [[Name]]
필드가 null이 아닌 값을 가진 것을 이름이 있는 매핑이라고 부릅니다.
참고 1
즉시 실행 함수식에서 함수와 변수명을 바꾸거나 함수명을 제거하는 미니파이어
다음 열거는 ECMAScript 구문 문법의 생성식과, 소스맵
생성기가 이름이 있는 매핑을 생성해야 하는 해당 토큰 혹은 비터미널(생성식의 오른쪽 항)을 나열합니다. 이때 생성되는 매핑 항목은 9.2.3 절을 따라야 합니다.
이 열거는 반드시 포함해야 하는 "최소한"의 항목으로 이해되어야 하며, 일반적으로 소스맵 생성기는 추가적인 이름 매핑을 자유롭게 생성할 수 있습니다.
참고 2
이 목록에는 생성기가 "추가적으로" 이름 매핑을 생성할 수 있는 토큰도 포함되어 있습니다. 이는 기존 도구가 이름 매핑을 생성하거나 필요로 하는 현실을 반영합니다.
같은 이름에 대해 중복된 이름 매핑을 생성하는 것은 비교적 저렴합니다: 이름 인덱스는 서로 상대적으로 인코딩되므로 이후 같은 이름으로 매핑할 경우
0(A)로 인코딩됩니다.
추상 연산 DecodeSourceMapSources는 baseURL(URL), sourceRoot(문자열
또는 null), sources(문자열 또는 null을 포함하는 리스트),
sourcesContent(문자열 또는 null을 포함하는 리스트),
ignoreList(0 이상의 정수로 구성된 리스트)를
인자로 받아서 디코딩된 소스 레코드를 반환합니다. 호출 시 다음 절차를 수행합니다:
sourceMap.[[Mappings]] 값을
리스트
연결로 sourceMap.[[Mappings]]와 offsetMappings를 결합한
값으로 설정합니다.
previousOffsetPosition을 offsetPosition로 설정합니다.
offsetMappings가 비어 있지 않으면 previousLastMapping을
offsetMappings의 마지막 요소로 설정합니다.
sourceMap을 반환합니다.
참고
구현체는 인덱스 소스맵의 각 섹션을 합치지 않고 따로 저장하거나, 예를 들어 이진 탐색을 사용할 수도 있습니다.
11 소스맵 가져오기
11.1 생성 코드와 소스맵 연결
소스맵 포맷은 언어와 플랫폼에 독립적인 것을 목표로 하지만, 웹 서버에서 호스팅되는 자바스크립트의 예상 사용 사례에 대해 어떻게 참조하는지 정의하는 것이 유용합니다.
출력에 소스맵을 연결하는 방법은 두 가지가 있습니다. 첫 번째 방법은 서버가 HTTP 헤더를 추가하는 지원이 필요하고, 두 번째 방법은 소스 내에 주석을 추가하는 방식입니다.
소스맵은 WHATWG URL에 정의된 것처럼 URL을 통해
연결됩니다. 특히, URI에 허용되지 않은 문자는 퍼센트 인코딩되어야 하며, 데이터 URI일 수도 있습니다. 데이터 URI와 sourcesContent를 함께 사용하면 완전히 자체
포함된 소스맵을 만들 수 있습니다.
HTTP sourcemap 헤더는 소스 주석보다 우선하며, 둘 다 존재할 경우 헤더의 URL을 이용해 소스맵 파일을 해석해야 합니다.
소스맵 URL을 가져오는
방법에 관계없이 같은 과정을 통해 해석됩니다. 그 과정은 아래와 같습니다.
소스맵 URL이 절대
경로가 아니라면, 생성 코드의
source origin에 상대적으로 해석됩니다. source origin은 아래 경우 중 하나로 결정됩니다:
생성 소스가 src 속성이 있는 script 요소에 연결되어 있지 않고 생성 코드에
//# sourceURL 주석이 있으면, 그 주석을 사용해 source origin을 정해야 합니다.
참고
이전에는 //@ sourceURL이었으며,
//@ sourceMappingURL과 마찬가지로 두 형태 모두 허용하는 것이 타당하지만
//#를 우선적으로 사용해야 합니다.
생성 코드가
script 요소에 연결되고, script 요소가 src 속성을 가지면, script 요소의 src 속성이 source origin입니다.
생성 코드가
script 요소에 연결되어 있지만 src 속성이 없다면, source origin은 페이지의 origin입니다.
생성 코드가
eval()이나 new Function()으로 문자열 평가 시에는 source origin은 페이지의 origin입니다.
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을 파싱 방식으로 추출하면 null을 반환하지만,
파싱
없이 추출하면 foo.js.map이 반환됩니다.
참고 2
소스맵
URL을 추출하는 여러 방법이 서로 다른 결과를 낼 수 있으며, 이는 보안이나 프라이버시 문제를 일으킬 수 있습니다.
소스맵을 감지해야 하는 구현체는 두 알고리즘을 모두 적용해 결과가 같음을 확인하는 것이 권장됩니다.
이 문제를 해결하는 방안이 향후 표준 버전에 반영될 예정이며, 아래 알고리즘에서
U+0060 (`), U+0022 ("), U+0027 ('), 또는 U+002A U+002F (*/) 문자가 포함된 주석이 있으면
조기 종료하는 방식이 도입될 예정입니다.
11.1.2.1 JavaScriptExtractSourceMapURL ( source )
추상 연산 JavaScriptExtractSourceMapURL은 source(문자열)를 인자로 받아
문자열 또는 null을 반환합니다.
JavaScript 소스에서 소스맵 URL을
추출합니다.
구현 방식은 파싱
방식 혹은
파싱
없이 중 하나입니다.
token이 SingleLineComment 또는
MultiLineComment가 아니라면 null 반환
comment를 token의 내용으로 설정
sourceMapURL을 MatchSourceMapURL(comment)로 설정
sourceMapURL이 문자열이면 그 값을 반환
null 반환
소스맵
URL을 파싱 없이 추출하는 방법:
lines를 StringSplit(source, «
"\u000D\u000A", "\u000A",
"\u000D", "\u2028",
"\u2029" »)로 구분
NOTE: 위의 정규식은 LineTerminatorSequence에 해당
lastURL을 null로 설정
lines의 각 문자열 lineStr에 대해:
line을 StringToCodePoints(lineStr)로
설정
position을 0으로 설정
lineLength를 line의 길이로 설정
position < lineLength인 동안 반복
first를 line[position]로 설정
position을 1 증가
first가 U+002F이고 position <
lineLength이면:
second를 line[position]로 설정
position을 1 증가
second가 U+002F면:
comment를 substring(lineStr,
position, lineLength)로 설정
sourceMapURL을 MatchSourceMapURL(comment)로
설정
sourceMapURL이 문자열이면 lastURL에
할당
position을 lineLength로 설정
그 외 second가 U+002A면:
commentCp를 빈 리스트로 설정
position + 1 < lineLength
동안 반복
c1을
line[position]로 설정
position을 1 증가
c2를
line[position]로 설정
c1이 U+002A, c2가
U+002F면:
position을 1 증가
sourceMapURL을 MatchSourceMapURL(CodePointsToString(commentCp))로
설정
sourceMapURL이 문자열이면
lastURL에 할당
c1을 commentCp에 추가
그 외:
lastURL을 null로 설정
그 외 first가 ECMAScript WhiteSpace가 아니라면:
lastURL을 null로 설정
NOTE: 주석이 아닌 코드 문자를 찾을 때 lastURL을
null로 초기화
lastURL 반환
참고 1
위 알고리즘은 소스 행을 역순으로 순회하며 sourceMappingURL 주석이 포함된 행 발견 시 빨리 반환하도록 설계되었습니다.
참고 2
위 알고리즘은 다음 JavaScript 코드와 동일합니다:
constJS_NEWLINE = /^/m;
// 아래 정규 표현식은 다음을 구분합니다:// - single-line comments// - "single-line" multi-line comments// - unclosed multi-line comments// - just trailing whitespaces// - a code character// 아래 반복문은 각 경우를 구분합니다.constJS_COMMENT =
/\s*(?:\/\/(?<single>.*)|\/\*(?<multi>.*?)\*\/|\/\*.*|$|(?<code>[^\/]+))/uym;
constPATTERN = /^[@#]\s*sourceMappingURL=(\S*?)\s*$/;
let lastURL = null;
for (const line of source.split(JS_NEWLINE)) {
JS_COMMENT.lastIndex = 0;
while (JS_COMMENT.lastIndex < line.length) {
let commentMatch = JS_COMMENT.exec(line).groups;
let comment = commentMatch.single ?? commentMatch.multi;
if (comment != null) {
let match = PATTERN.exec(comment);
if (match !== null) lastURL = match[1];
} elseif (commentMatch.code != null) {
lastURL = null;
} else {
// 공백이나 미닫힌 주석만 나온 경우// Assert: JS_COMMENT.lastIndex === line.length
}
}
}
return lastURL;
11.1.2.1.1 MatchSourceMapURL ( comment )
추상 연산 MatchSourceMapURL은 comment(문자열) 인자를 받아 none 또는
문자열을 반환합니다. 호출 시 다음을 실행합니다:
pattern를 RegExpCreate("^[@#]\s*sourceMappingURL=(\S*?)\s*$",
"")로 설정
match를 RegExpExec(pattern,
comment)로 설정
match가 null이 아니면 Get(match, "1")을 반환
none 반환
참고
이 주석 접두사는 원래 //@였으나, Internet Explorer의 조건부 컴파일과
충돌하여 //#로 변경되었습니다.
소스맵 생성기는 반드시 //#만 내보내야 하며, 소스맵 소비자는 //@와 //# 모두
허용해야 합니다.
11.1.2.2 CSSExtractSourceMapURL ( source )
추상 연산 CSSExtractSourceMapURL은 source(문자열) 인자를 받아 문자열 또는 null을
반환합니다. CSS 소스에서 소스맵 URL을
추출합니다.
CSS에서 소스맵
URL을 추출하는 방식은 JavaScript와 유사하지만, CSS는 /* ... */ 스타일의
주석만 지원합니다.
11.1.2.3 WebAssemblyExtractSourceMapURL ( bytes )
추상 연산 WebAssemblyExtractSourceMapURL은 bytes(Data
Block) 인자를 받아 문자열 또는 null을 반환합니다.
WebAssembly 바이너리 소스에서 소스맵 URL을
추출합니다.
module를 module_decode(bytes)로 설정
module이 WebAssembly 오류이면 null 반환
module의 각 custom sectioncustomSection마다 반복
name을 customSection의 name 값으로 설정
CodePointsToString(name)이
"sourceMappingURL"이면:
value를 customSection의 bytes로 설정
CodePointsToString(value)를
반환
null 반환
WebAssembly는 텍스트 포맷이 아니고 주석을 지원하지 않으므로 단일 명확한 추출 방식만 지원합니다. URL은 WebAssembly 이름으로 인코딩되어 custom section의 내용으로
저장됩니다. WebAssembly 코드를 생성하는 도구가 sourceMappingURL 이름의 custom section을 둘 이상
생성하면 잘못된 것입니다.
11.2 소스맵 가져오기
11.2.1 FetchSourceMap ( url )
추상 연산 FetchSourceMap은 url(URL)을 인자로 받아 Promise를 반환합니다. 호출 시 다음을 수행합니다:
promiseCapability를 NewPromiseCapability(%Promise%)로 설정
request를 request로,
request
URL을 url로 설정하여 생성
processResponseConsumeBody를 매개변수 (response, bodyBytes)를
받으며 promiseCapability와 url을 캡처하는 Abstract Closure로,
다음을 실행:
bodyBytes가 null 또는 failure면
Call(promiseCapability.[[Reject]], undefined, « 새로운
TypeError ») 실행
일반적으로 소스맵은 생성된 파일과 동일한 이름에 .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 언어 중립적 스택 매핑
소스 언어에 대한 지식 없이 수행하는 스택 트레이싱 매핑은
covered되지 않습니다.
B.2 다단계 매핑
최근에는 도구가 일부 DSL(템플릿)이나 TypeScript → JavaScript → minified JavaScript 등 여러 단계를 거쳐 소스를 생성한 뒤 최종 소스맵을
만드는 경우가 많아지고 있습니다.
이 문제는 두 가지 방법 중 하나로 처리할 수 있습니다. 쉬운 방법이지만 정보가 손실되는 방식은 과정 중간의 단계를 디버깅 목적상 무시하는 것이고, 변환의 소스 위치 정보가
무시되거나(중간 변환이 “원본 소스”로 간주됨) 혹은 위치 정보가 이어지도록(중간 변환은 숨김) 구현하는 것입니다.
보다 완전한 방식은 다단계 매핑을 지원하는 것입니다. 즉, 원본 소스에도 소스맵 참조가 있다면, 사용자가 그 참조도 사용할 수 있게 하는 것입니다.
단, 자바스크립트 외의 언어에서는 "소스맵 참조"가 어떻게 생겼는지 명확하지 않습니다. 특히 자바스크립트 스타일의 단일행 주석을 지원하지 않는 언어에서는 소스맵 참조가 어떻게
제공되는지 불분명합니다.
Annex C (informative) 외부 명세에서 정의된 용어
본 문서에서 사용한 ECMA-262 이외의 외부 명세에서 정의된 모든 용어와 알고리즘을 나열합니다.
이 명세서는 GitHub에서 평문 소스 포맷인 Ecmarkup으로 작성되었습니다. Ecmarkup은 HTML과 Markdown의 방언으로,
ECMAScript 명세를 평문으로 작성하고, 본 문서의 편집 규약을 따르면서 완전한 기능의 HTML 렌더링으로 가공할 수 있는 프레임워크 및 도구 세트를 제공합니다. Ecmarkup은
Grammarkdown을 통한 문법 정의와 Ecmarkdown을 통한 알고리즘 기술 등 다양한 형식과 기술을 통합합니다. 이 명세서의
PDF 버전은 HTML 렌더링을 PDF로 인쇄하여 생성됩니다.
이 명세서의 첫 에디션은 Bikeshed라는 또 다른 평문 소스 포맷(HTML과 Markdown
기반)으로 작성되었습니다.
This draft document may be copied and furnished to others, and derivative works that comment on or
otherwise explain it or assist in its implementation may be prepared, copied, published, and
distributed, in whole or in part, without restriction of any kind, provided that the above copyright
notice and this section are included on all such copies and derivative works. However, this document
itself may not be modified in any way, including by removing the copyright notice or references to
Ecma International, except as needed for the purpose of developing any document or deliverable
produced by Ecma International.
This disclaimer is valid only prior to final version of this document. After approval all rights on
the standard are reserved by Ecma International.
The limited permissions are granted through the standardization phase and will not be revoked by Ecma
International or its successors or assigns during this time.
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.
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:
Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
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.
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.