Copyright © 2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
이 명세는 고해상도 시간 명세 [HR-TIME-3]를 확장하여 고해상도 성능 메트릭 데이터를 저장하고 조회하는 메서드를 제공합니다.
이 섹션은 이 문서가 출판될 당시의 상태를 설명합니다. 현재 W3C 출판물 목록과 이 기술 보고서의 최신 개정본은 W3C 표준 및 초안 인덱스에서 확인할 수 있습니다: https://www.w3.org/TR/.
이 Performance Timeline 명세는 첫 번째 버전의 [PERFORMANCE-TIMELINE]을 대체하며 다음 내용을 포함합니다:
Performance
인터페이스 정의 확장
[HR-TIME-3];
PerformanceEntry
노출
[WORKERS];
PerformanceObserver
지원
추가
이 문서는 Web Performance Working Group이 권고안 트랙을 사용하여 후보 권고안 초안으로 발행한 것입니다.
후보 권고안으로서의 출판은 W3C 및 그 회원들의 승인/지지를 의미하지 않습니다. 후보 권고안 초안은 이전 후보 권고안에서 작업 그룹이 이후 후보 권고안 스냅샷에 포함하려는 변경 사항을 통합합니다.
이 문서는 초안이며 언제든지 업데이트, 교체 또는 폐기될 수 있습니다. 진행 중인 작업 외의 인용은 적절하지 않습니다.
이 문서는 W3C 특허 정책에 따라 운영되는 그룹이 제작했습니다. W3C는 공개 특허 공개 목록 을 관리하며, 해당 그룹의 산출물과 관련하여 제출된 특허 공개 내역과 특허 공개 방법에 대한 안내도 포함되어 있습니다. 특정 특허에 대해 실제로 알고 있고, 그 특허가 필수 청구항 을 포함한다고 생각되는 경우, W3C 특허 정책 제6절에 따라 정보를 공개해야 합니다.
이 문서는 2023년 11월 3일 W3C 프로세스 문서에 의해 관리됩니다.
이 섹션은 비규범적입니다.
웹 애플리케이션의 성능 특성을 정확하게 측정하는 것은 웹 애플리케이션을 더욱 빠르게 만드는 데 중요한 요소입니다. 이 명세는 웹 개발자가 웹 애플리케이션의 전체 라이프사이클에서 다양한 성능 지표에 접근하고, 계측하며, 조회할 수 있도록 하는 Performance Timeline 기본 요소를 정의합니다.
[NAVIGATION-TIMING-2], [RESOURCE-TIMING-2], [USER-TIMING-2] 는 각각 문서의 내비게이션, 페이지의 리소스, 개발자 스크립트와 관련된 타이밍 정보를 정의하는 명세의 예시입니다. 이들 및 기타 성능 인터페이스는 웹 애플리케이션의 Performance Timeline을 설명하는 성능 지표를 정의합니다. 예를 들어, 다음 스크립트는 개발자가 문서의 내비게이션, 페이지의 리소스, 개발자 스크립트와 관련된 성능 지표를 얻기 위해 Performance Timeline에 접근하는 방법을 보여줍니다:
<!doctype html>
<html>
<head></head>
<body onload="init()">
<img id="image0" src="https://www.w3.org/Icons/w3c_main.png" />
<script>
function init() {
// see [[USER-TIMING-2]]
performance.mark("startWork");
doWork(); // 개발자 코드
performance.mark("endWork");
measurePerf();
}
function measurePerf() {
performance
.getEntries()
.map(entry => JSON.stringify(entry, null, 2))
.forEach(json => console.log(json));
}
</script>
</body>
</html>
또한 개발자는 Performance Timeline을 관찰하여 새로운 성능 지표 또는 선택적으로 지정된 타입의 이전에
버퍼링된 성능 지표에 대한 알림을 PerformanceObserver
인터페이스를 통해 받을 수 있습니다.
PerformanceObserver
인터페이스가 추가되었으며, 첫 번째 예제에 나온
버퍼 기반 접근 방식의 한계를 해결하기 위해 설계되었습니다. PerformanceObserver 인터페이스를 사용하면 애플리케이션은 다음과 같은 이점을 얻습니다:
개발자는 가능한 경우 PerformanceObserver
를 사용할 것을 권장합니다. 또한 새로운 성능 API
및 지표는 PerformanceObserver
인터페이스를 통해서만 제공될 수 있습니다. 옵저버는
생성자에서 콜백을 지정하고, observe()
메서드를 통해 관심 있는 성능 엔트리를 지정하여
동작합니다.
사용자 에이전트는 콜백을 실행할 시점을 선택하며, 콜백은 큐에 추가된 성능 엔트리를 받게 됩니다.
PerformanceObserver
인터페이스를 사용할 때 초기 페이지 로드와 관련된
특별한 고려사항이 있습니다: 등록이 활성화되어야 이벤트를 받을 수 있지만, 등록 스크립트가 사용 가능하지 않거나 크리티컬 패스에 포함되지 않을 수도 있습니다. 이를 해결하기 위해 사용자
에이전트는 페이지가 구성되는 동안 일부 이벤트를 버퍼링하며, 이러한 버퍼링된 이벤트는 옵저버를 등록할 때 buffered
플래그를 통해 접근할 수 있습니다.
플래그가 설정되면 사용자 에이전트는 지정된 엔트리 타입에 대해 버퍼링된 이벤트를 조회 및 디스패치하고, observe()
호출 이후 첫 번째 콜백에서 전달합니다.
버퍼링되는 이벤트의 개수는 해당 지표를 정의하는 명세에 의해 결정되며, 버퍼링은 최초 N개의 이벤트만을 위한 것이며, 무제한 또는 지속적인 버퍼링이 아닙니다.
<!doctype html>
<html>
<head></head>
<body>
<img id="image0" src="https://www.w3.org/Icons/w3c_main.png" />
<script>
// 사용하려는 엔트리 타입이 지원되지 않을 때를 감지합니다.
function detectSupport(entryTypes) {
for (const entryType of entryTypes) {
if (!PerformanceObserver.supportedEntryTypes.includes(entryType)) {
// 클라이언트 측 분석에 |entryType|이 지원되지 않음을 알립니다.
}
}
}
detectSupport(["resource", "mark", "measure"]);
const userTimingObserver = new PerformanceObserver(list => {
list
.getEntries()
// 관심 있는 값을 가져옵니다
.map(({ name, entryType, startTime, duration }) => {
const obj = {
"Duration": duration,
"Entry Type": entryType,
"Name": name,
"Start Time": startTime,
};
return JSON.stringify(obj, null, 2);
})
// 콘솔에 표시합니다.
.forEach(console.log);
// 이벤트 처리 후 연결 해제합니다.
userTimingObserver.disconnect();
});
// User-Timing에 대해 새로운 이벤트를 구독합니다.
userTimingObserver.observe({entryTypes: ["mark", "measure"]});
const resourceObserver = new PerformanceObserver(list => {
list
.getEntries()
// 관심 있는 값을 가져옵니다
.map(({ name, startTime, fetchStart, responseStart, responseEnd }) => {
const obj = {
"Name": name,
"Start Time": startTime,
"Fetch Start": fetchStart,
"Response Start": responseStart,
"Response End": responseEnd,
};
return JSON.stringify(obj, null, 2);
})
// 콘솔에 표시합니다.
.forEach(console.log);
// 이벤트 처리 후 연결 해제합니다.
resourceObserver.disconnect();
});
// Resource Timing에 대해 버퍼링된 이벤트를 조회하고 새로운 이벤트를 구독합니다.
resourceObserver.observe({type: "resource", buffered: true});
</script>
</body>
</html>
비규범적으로 표시된 섹션과 저작 가이드라인, 도해, 예제, 참고 사항은 모두 비규범적입니다. 이 명세의 그 외 모든 내용은 규범적입니다.
이 문서의 MUST, MUST NOT, SHOULD 키워드는 BCP 14 [RFC2119] [RFC8174] 에서 설명한 대로, 반드시 대문자로 표시될 때만 이 의미대로 해석해야 합니다.
알고리즘이나 특정 단계로 기술된 적합성 요구 사항은 결과가 동일하다면 어떤 방식으로든 구현할 수 있습니다. (특히 이 명세에 정의된 알고리즘은 따라하기 쉽도록 설계된 것이며, 성능을 위한 것이 아닙니다).
각 글로벌 오브젝트는 다음을 가진다:
DOMString
이며,
버퍼가 속한 엔트리 타입을 나타낸다. 이 맵의
값은 다음 튜플이다:
PerformanceEntry
객체를 저장하며, 초기에는 비어 있음)
boolean
availableFromTimeline (해당 엔트리 타입의 레지스트리 값으로 초기화)각 Document는 다음을 가진다:
PerformanceEntry
, 초기에는 설정되지 않음)관련 성능 엔트리 튜플을 얻으려면, entryType과 globalObject를 입력값으로 하여 다음 단계를 수행한다:
Performance
인터페이스 확장
이 내용은 [HR-TIME-3]의 Performance
인터페이스를 확장하며,
성능 타임라인에서 성능 메트릭 데이터를 조회할 때 사용하는
성능 관련 속성과 메서드를 포함한다.
WebIDLpartial interface Performance {
PerformanceEntryList
getEntries
();
PerformanceEntryList
getEntriesByType
(DOMString type);
PerformanceEntryList
getEntriesByName
(DOMString name, optional DOMString type);
};
typedef sequence<PerformanceEntry
> PerformanceEntryList
;
PerformanceEntryList
는 PerformanceEntry
시퀀스를 나타내며,
개발자에게 자바스크립트 배열에서 제공되는 모든 편의 메서드를 제공한다.
이름과 타입으로 버퍼 맵 필터링 알고리즘에서
name과 type을 null
로 설정해 반환된 PerformanceEntryList
객체를 반환한다.
이름과 타입으로 버퍼 맵 필터링 알고리즘에서
name을 null
, type을 메서드의 입력 type
파라미터로 설정해 반환된
PerformanceEntryList
객체를 반환한다.
이름과 타입으로 버퍼 맵 필터링 알고리즘에서
name을 메서드 입력 name
파라미터로, type을 선택적 entryType
이 생략된 경우
null
, 그렇지 않으면 메서드의 입력 type
파라미터로 설정해 반환된
PerformanceEntryList
객체를 반환한다.
PerformanceEntry
인터페이스는 다양한 성능 메트릭의 성능 데이터를 담는다.
WebIDL[Exposed=(Window,Worker)]
interface PerformanceEntry
{
readonly attribute unsigned long long id
;
readonly attribute DOMString name
;
readonly attribute DOMString entryType
;
readonly attribute DOMHighResTimeStamp startTime
;
readonly attribute DOMHighResTimeStamp duration
;
[Default] object toJSON
();
};
name
PerformanceEntry
객체의 식별자를 나타낸다. 이 식별자는 반드시 유일할
필요는 없다.
entryType
모든 entryType
값은 관련 레지스트리에 정의되어 있다.
예시: "mark"
, "measure"
[USER-TIMING-2],
"navigation"
[NAVIGATION-TIMING-2],
그리고 "resource"
[RESOURCE-TIMING-2].
startTime
duration
duration
속성의 getter 단계는 this의 종료 시간이 0이면 0을 반환하고, 그렇지 않으면
this의 종료 시간 - this의 startTime
값을 반환한다.
navigationId
toJSON
이 호출되면, [WebIDL]의 기본 toJSON 단계를 실행한다.
PerformanceEntry
는 DOMHighResTimeStamp
종료 시간을 가지며,
초기값은 0이다.
PerformanceEntry
를 초기화한다
entry에 대해
DOMHighResTimeStamp
startTime,
DOMString
entryType, DOMString
name, 그리고 선택적으로 DOMHighResTimeStamp
endTime (기본값 0
)이 주어졌을 때:
startTime
을
startTime으로 초기화한다.
entryType
을
entryType으로 초기화한다.
name
을
name으로 초기화한다.
PerformanceObserver
인터페이스는
성능 타임라인을 관찰하여 새로운 성능 메트릭이 기록될 때와 선택적으로 버퍼링된 성능 메트릭에 대한 알림을
받을 수 있다.
각 PerformanceObserver
는 다음과 같은 연관 개념을 가진다:
PerformanceObserverCallback
옵저버 콜백
PerformanceEntryList
객체인 옵저버 버퍼
"undefined"
인 DOMString
옵저버 타입PerformanceObserver(callback)
생성자는 옵저버 콜백을 callback으로 설정하여 새로운
PerformanceObserver
객체를 생성하고 반환해야 한다.
등록된 성능
옵저버는 구조체이며,
옵저버 멤버( PerformanceObserver
객체)와 옵션 리스트 멤버( PerformanceObserverInit
딕셔너리 리스트)로 구성된다.
WebIDLcallback PerformanceObserverCallback
= undefined (PerformanceObserverEntryList
entries,
PerformanceObserver
observer,
optional PerformanceObserverCallbackOptions
options = {});
[Exposed=(Window,Worker)]
interface PerformanceObserver
{
constructor
(PerformanceObserverCallback
callback);
undefined observe
(optional PerformanceObserverInit
options = {});
undefined disconnect
();
PerformanceEntryList
takeRecords
();
[SameObject] static readonly attribute FrozenArray<DOMString> supportedEntryTypes
;
};
성능 오버헤드를 최소화하려면 애플리케이션은 관심 있는 이벤트 타입만 구독하고, 더 이상 성능 데이터를 관찰할 필요가 없을 때 옵저버를 해제해야 한다. 이름으로 필터링하는 기능은 모든 이벤트 타입을 암묵적으로 구독해야 하므로 지원하지 않으며, 이는 많은 이벤트가 생성될 수 있으므로 권장되지 않는다.
WebIDLdictionary PerformanceObserverCallbackOptions
{
unsigned long long droppedEntriesCount
;
};
droppedEntriesCount
PerformanceObserver
의 드롭된 엔트리 필요 여부가 설정된 경우에 해당한다.observe()
메서드는 사용자 에이전트에게 옵저버를 등록하도록
지시하며, 다음 단계를 실행해야 한다:
entryTypes
와 type
멤버가 모두 생략된 경우, "TypeError
"를 throw한다.
entryTypes
가 존재하고, 다른 멤버도
존재하면 "TypeError
"를
throw한다.
"undefined"
인 경우:
"single"
이고 options의
entryTypes
가 존재하면,
"InvalidModificationError
"를
throw한다.
"multiple"
이고
options의 type
가 존재하면, "InvalidModificationError
"를
throw한다.
"multiple"
이면, 다음 단계를 실행한다:
entryTypes
시퀀스로
한다.
"single"
임을 단언한다.
type
이
relevantGlobal의 지원되는 엔트리 타입 동결 배열에 포함되지
않으면, 이 단계들을 중단한다. 사용자 에이전트는 SHOULD 이 상황을 개발자에게 알려야 한다. 예를 들어, 콘솔
경고가 적절하다.
PerformanceObserverInit
아이템 currentOptions가 있고,
그 type
이
options의 type
과 같으면,
currentOptions를 options로 교체한다.
buffered
플래그가 설정된
경우:
type
와
relevantGlobal의 관련 성능 엔트리 튜플로 한다.
tuple의 성능 엔트리 버퍼의 각 entry에 대해:
PerformanceObserver
객체는 항상 observe()
를 options의
entryTypes
가 설정된 상태로
호출하거나, options의 type
이 설정된
상태로 호출해야 한다. 만약 하나의 PerformanceObserver
가 observe()
를 entryTypes
와 함께 호출하고, 다시
type
과 함께 호출하면, 예외가 발생한다. 이는 호출이
어떻게 중첩되는지 혼란을 방지하기 위한 것이다. entryTypes
를 사용할 때는 PerformanceObserverInit
의 다른 파라미터를
사용할 수 없다. 또한, 여러 번 observe()
를
호출하면 이전 값을 덮어쓰며, 한 번의 호출이면 충분하다. 반면 type
을 사용할
때는 호출이 쌓인다. 같은 type
으로 여러 번 호출하면 덮어쓴다.
WebIDLdictionary PerformanceObserverInit
{
sequence<DOMString> entryTypes
;
DOMString type
;
boolean buffered
;
};
entryTypes
type
buffered
WebIDL[Exposed=(Window,Worker)]
interface PerformanceObserverEntryList
{
PerformanceEntryList
getEntries
();
PerformanceEntryList
getEntriesByType
(DOMString type);
PerformanceEntryList
getEntriesByName
(DOMString name, optional DOMString type);
};
각 PerformanceObserverEntryList
객체는 엔트리 리스트를
가지며,
PerformanceEntryList
로 구성되고, 생성 시
초기화된다.
이름과 타입으로 버퍼 필터링 알고리즘에서 this의 엔트리 리스트,
name과 type을 null
로 설정해 반환된 PerformanceEntryList
객체를 반환한다.
이름과 타입으로 버퍼 필터링 알고리즘에서 this의 엔트리 리스트,
name을 null
, type을 메서드의 입력 type
파라미터로 설정해 반환된 PerformanceEntryList
객체를 반환한다.
이름과 타입으로 버퍼 필터링 알고리즘에서 this의 엔트리 리스트,
name을 메서드 입력 name
파라미터로, type을 선택적 entryType
이
생략된 경우 null
, 그렇지 않으면 메서드의 입력 type
파라미터로 설정해 반환된 PerformanceEntryList
객체를 반환한다.
takeRecords()
메서드는 this의 옵저버 버퍼의 복사본을 반환하며, this의 옵저버 버퍼도 비워야 한다.
disconnect()
메서드는 다음을 수행해야 한다:
supportedEntryTypes
속성각 글로벌 오브젝트는 연관된 지원되는 엔트리 타입의 동결 배열을 가지며, 이는 레지스트리에서 해당 글로벌 오브젝트가 지원하는 문자열의 시퀀스를 알파벳순으로 정렬한 뒤 FrozenArray 생성으로 초기화한다.
supportedEntryTypes
속성의 getter가 호출되면 다음 단계를 실행한다:
이 속성은 웹 개발자가 사용자 에이전트가 지원하는 엔트리 타입을 쉽게 알 수 있도록 해준다.
PerformanceEntry 큐에 추가(newEntry)하려면 다음 단계를 실행한다:
id
가 설정되지 않은 경우:
PerformanceObserver
객체 집합으로 한다.
entryType
값으로 한다.
navigationId
를
relevantGlobal의 연관된
document의 가장 최근 내비게이션의 id
값으로 설정한다.
navigationId
를 null로 설정한다.regObs의 옵션 리스트에 PerformanceObserverInit
options가 있고, 그 entryTypes
가
entryType을 포함하거나, type
가
entryType과 같다면:
PerformanceObserver 작업 큐에 추가를 요청받으면, relevantGlobal을 인자로 다음 단계를 실행한다:
PerformanceObserverEntryList
로
생성하며,
엔트리 리스트를 entries로 설정한다.
PerformanceObserverInit
item에 대해:
type
또는 entryTypes
에
나타나는 각 DOMString
entryType에 대해:
PerformanceObserverCallbackOptions
로
생성하며,
droppedEntriesCount
를
droppedEntriesCount가 null이 아니면 해당 값으로 하고, 아니면 설정하지 않는다.
report
",
po를 전달한다.
성능 타임라인 작업 큐는 낮은 우선순위 큐로, 성능 모니터링 코드의 영향을 최소화하기 위해 사용자 에이전트가 가능하다면 유휴 시간에 처리해야 한다.
선택적 name과 type으로 이름과 타입으로 버퍼 맵 필터링 알고리즘을 실행하면 다음 단계를 따른다:
startTime
기준으로 시간순으로 정렬한다.
이름과 타입으로 버퍼 필터링 알고리즘을 buffer, name, type을 인자로 실행하면 다음 단계를 따른다:
PerformanceEntry
entry에 대해 다음
단계 실행:
startTime
기준으로 시간순으로 정렬한다.
성능 엔트리 버퍼가 가득 찼는지 확인 알고리즘을 tuple을 인자로 실행하면 다음 단계를 따른다:
id 생성을 PerformanceEntry
entry에 요청받으면 다음 단계를 실행한다:
사용자 에이전트는 마지막 성능 엔트리 ID를 매번 작은 랜덤 정수만큼 증가시킬 수 있다. 모든 글로벌 오브젝트의 마지막 성능 엔트리 ID를 하나의 글로벌 랜덤 정수로 증가시키면 교차 출처 정보 노출이 발생할 수 있으므로 반드시 피해야 한다.
마지막 성능 엔트리 ID는 초기값이 랜덤이며, 사용자 에이전트가 선택한 작은 숫자만큼 증가한다. 이는 개발자가 해당 값을 웹 애플리케이션에서 생성된 엔트리 개수 카운터로 간주하는 것을 방지하기 위함이다.
이 명세는 [HR-TIME-3]에서 정의된 Performance
인터페이스를 확장하며,
성능 타임라인에서 엔트리를 큐잉 및 조회하는 메서드를 제공합니다.
고해상도 타이밍 정보를 노출할 때의 프라이버시 고려사항은 [HR-TIME-3]를 참고하세요.
새로운 성능 엔트리를 도입하는 각 명세는 자체 프라이버시 고려사항을 별도로 가져야 합니다.
마지막 성능 엔트리 ID는 의도적으로 랜덤 값으로 초기화되며,
새로운 PerformanceEntry
가 큐에 추가될 때마다 또 다른 작은 값만큼 증가합니다.
사용자 에이전트는 모든 사용자에게 일관된 증가값을 사용할 수도 있고, 각 글로벌 오브젝트마다 다른 증가값을
선택하거나,
각 PerformanceEntry
마다 새로운 랜덤 증가값을 선택할 수도 있습니다.
그러나 교차 출처 정보 유출과 지문 채취(fingerprinting)를 방지하기 위해,
사용자 에이전트는 고유한 랜덤 정수를 선택해 모든 PerformanceEntry
객체에 일관된 증가값으로
사용해서는 안 됩니다.
이는 모든 글로벌 오브젝트에 해당됩니다.
이 명세는 [HR-TIME-3]에서 정의된 Performance
인터페이스를 확장하며,
성능 타임라인에서 엔트리를 큐잉 및 조회하는 메서드를 제공합니다.
고해상도 타이밍 정보를 노출할 때의 보안 고려사항은 [HR-TIME-3]를 참고하세요.
새로운 성능 엔트리를 도입하는 각 명세는 자체 보안 고려사항을 별도로 가져야 합니다.
WebIDLpartial interface Performance {
PerformanceEntryList
getEntries
();
PerformanceEntryList
getEntriesByType
(DOMString type);
PerformanceEntryList
getEntriesByName
(DOMString name, optional DOMString type);
};
typedef sequence<PerformanceEntry
> PerformanceEntryList
;
[Exposed=(Window,Worker)]
interface PerformanceEntry
{
readonly attribute unsigned long long id
;
readonly attribute DOMString name
;
readonly attribute DOMString entryType
;
readonly attribute DOMHighResTimeStamp startTime
;
readonly attribute DOMHighResTimeStamp duration
;
readonly attribute unsigned long long navigationId
;
[Default] object toJSON
();
};
callback PerformanceObserverCallback
= undefined (PerformanceObserverEntryList
entries,
PerformanceObserver
observer,
optional PerformanceObserverCallbackOptions
options = {});
[Exposed=(Window,Worker)]
interface PerformanceObserver
{
constructor
(PerformanceObserverCallback
callback);
undefined observe
(optional PerformanceObserverInit
options = {});
undefined disconnect
();
PerformanceEntryList
takeRecords
();
[SameObject] static readonly attribute FrozenArray<DOMString> supportedEntryTypes
;
};
dictionary PerformanceObserverCallbackOptions
{
unsigned long long droppedEntriesCount
;
};
dictionary PerformanceObserverInit
{
sequence<DOMString> entryTypes
;
DOMString type
;
boolean buffered
;
};
[Exposed=(Window,Worker)]
interface PerformanceObserverEntryList
{
PerformanceEntryList
getEntries
();
PerformanceEntryList
getEntriesByType
(DOMString type);
PerformanceEntryList
getEntriesByName
(DOMString name, optional DOMString type);
};
이 작업에 기여해주신 Arvind Jain, Boris Zbarsky, Jatinder Mann, Nat Duca, Philippe Le Hegaret, Ryosuke Niwa, Shubhie Panicker, Todd Reifsteck, Yoav Weiss, Zhiheng Wang께 감사드립니다.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: