웹 IDL

현행 표준 — 최종 업데이트

참여하기:
GitHub whatwg/webidl (새 이슈 등록, 오픈된 이슈)
Matrix에서 채팅하기
커밋:
GitHub whatwg/webidl/커밋 내역
이 커밋 기준의 스냅샷
테스트:
web-platform-tests webidl/ (진행 중인 작업)
번역 (비규범):
日本語
简体中文
한국어

요약

이 표준은 웹 브라우저에서 구현될 인터페이스를 기술하기 위해 사용할 수 있는 인터페이스 정의 언어인 웹 IDL을 정의합니다.

1. 소개

이 섹션은 참고용입니다.

이 표준은 웹 브라우저에 구현될 인터페이스를 기술하는 데 사용할 수 있는 인터페이스 정의 언어, 웹 IDL을 정의합니다. 웹 IDL은 웹 플랫폼의 일반적인 스크립트 객체의 동작을 보다 쉽게 명세할 수 있도록 하는 다양한 기능을 가진 IDL 변형입니다. 웹 IDL로 기술된 인터페이스가 자바스크립트 실행 환경 내의 구조와 어떻게 대응되는지도 이곳에서 자세히 설명합니다.

구체적으로, 웹 IDL은 웹 플랫폼 객체의 표면 API를 명세하는 구문과, 그 API가 자바스크립트 구조로 어떻게 나타나는지 상세히 기술하는 자바스크립트 바인딩을 제공합니다. 이로 인해 글로벌 속성 설치, 숫자 입력 처리, 반복 동작 노출과 같은 일반적인 작업들이 웹 플랫폼 명세서 전체에서 일관성을 유지할 수 있습니다. 이러한 명세서들은 웹 IDL로 인터페이스를 기술하고, 프로즈로 API 고유의 세부사항을 명세합니다.

"자바스크립트"라는 용어는 공식 용어 ECMAScript가 아닌 ECMA-262를 의미하며, 자바스크립트라는 명칭이 더 널리 알려져 있기 때문에 사용합니다.

2. 인터페이스 정의 언어

이 섹션에서는 웹 IDL이라는 언어를 설명합니다. 이는 웹 플랫폼의 API를 정의하는 인터페이스를 명세하는 데 사용할 수 있습니다. 웹 API를 정의하는 명세서는 하나 이상의 IDL 프래그먼트를 포함하여, 해당 명세서에서 정의된 API의 인터페이스(객체가 가질 수 있는 상태와 동작)를 기술합니다. IDL 프래그먼트는 Definitions 문법 기호에 일치하는 일련의 정의입니다. 구현체가 지원하는 IDL 프래그먼트 집합은 순서가 없습니다. 전체 문법과 표기법 설명은 IDL 문법을 참고하세요.

IDL 프래그먼트에 등장할 수 있는 다양한 정의의 종류는 다음과 같습니다: 인터페이스, 부분 인터페이스 정의, 인터페이스 믹스인, 부분 믹스인 정의, 콜백 함수, 콜백 인터페이스, 네임스페이스, 부분 네임스페이스 정의, 딕셔너리, 부분 딕셔너리 정의, 타입 정의(typedef) 및 includes 문입니다. 모든 종류는 아래 섹션에서 정의됩니다.

각 정의 (Definition에 일치) 앞에는 확장 속성 목록(ExtendedAttributeList에 일치)이 올 수 있으며, 이는 해당 정의가 언어 바인딩에서 어떻게 처리될지 제어합니다. 이 명세서에서 정의된 언어 바인딩에 독립적인 확장 속성은 § 2.14 확장 속성에서, 자바스크립트 언어 바인딩에 특화된 것은 § 3.3 확장 속성에서 설명합니다.

[extended_attributes]
interface identifier {
  /* interface_members... */
};
Definitions ::
    ExtendedAttributeList Definition Definitions
    ε
Definition ::
    CallbackOrInterfaceOrMixin
    Namespace
    Partial
    Dictionary
    Enum
    Typedef
    IncludesStatement

아래는 IDL 프래그먼트의 예시입니다.

[Exposed=Window]
interface Paint { };

[Exposed=Window]
interface SolidColor : Paint {
  attribute double red;
  attribute double green;
  attribute double blue;
};

[Exposed=Window]
interface Pattern : Paint {
  attribute DOMString imageURL;
};

[Exposed=Window]
interface GraphicalWindow {
  constructor();
  readonly attribute unsigned long width;
  readonly attribute unsigned long height;

  attribute Paint currentPaint;

  undefined drawRectangle(double x, double y, double width, double height);

  undefined drawText(double x, double y, DOMString text);
};

여기서는 네 개의 인터페이스가 정의되고 있습니다. GraphicalWindow 인터페이스에는 두 개의 읽기 전용 속성, 하나의 쓰기 가능한 속성, 그리고 두 개의 연산이 정의되어 있습니다. GraphicalWindow 인터페이스를 구현하는 객체들은 해당 언어에 맞는 방식으로 이 속성과 연산을 노출합니다.

자바스크립트에서는, IDL 인터페이스의 속성들이 접근자 속성으로, 연산들은 모든 GraphicalWindow 객체의 프로토타입 객체에 내장 함수 객체(built-in function object)로서 데이터 속성으로 노출됩니다. 각 자바스크립트 객체는 GraphicalWindow를 구현하면 해당 프로토타입 객체를 프로토타입 체인에 갖게 됩니다.

GraphicalWindow에 등장하는 생성자 연산은 자바스크립트 구현체에서 생성자가 존재하도록 하여, new GraphicalWindow()를 호출하면 해당 인터페이스를 구현하는 새로운 객체를 반환합니다.

모든 인터페이스에는 [Exposed] 확장 속성이 붙어 있으며, 이로 인해 인터페이스가 realm의 글로벌 객체가 Window 객체인 경우에만 사용할 수 있도록 보장합니다.

2.1. 이름

모든 인터페이스, 부분 인터페이스 정의, 네임스페이스, 부분 네임스페이스 정의, 딕셔너리, 부분 딕셔너리 정의, 열거형, 콜백 함수, 콜백 인터페이스 및 타입 정의(typedef) (이들을 통틀어 이름이 있는 정의이라 함) 그리고 모든 상수, 속성, 딕셔너리 멤버는 식별자를 가지며, 일부 연산도 마찬가지입니다. 식별자는 선언 내 어딘가에 등장하는 identifier 토큰에 의해 결정됩니다:

참고: 연산은 getter, setter와 같은 특수 연산을 선언할 때 식별자가 없을 수 있습니다.

이러한 모든 구조에서, 식별자는 identifier 토큰 값에서 앞에 오는 U+005F (_)를 제거한 값입니다.

참고: 앞에 오는 U+005F (_)는 식별자가 예약어처럼 보이지 않게 하기 위해 사용되며, 예를 들어 "interface"라는 이름의 인터페이스를 정의할 수 있습니다. 식별자를 해제할 때는 앞의 U+005F (_)를 삭제합니다.

연산의 인자(argument)는 더 넓은 범위의 식별자 집합을 가질 수 있습니다. 연산 선언에서 인자의 식별자는 타입 뒤에 바로 명시되며, identifier 토큰 또는 ArgumentNameKeyword 심볼에 매칭되는 키워드 중 하나로 지정됩니다. 이런 키워드가 사용될 경우, 앞에 밑줄로 이스케이프할 필요가 없습니다.

interface interface_identifier {
  return_type operation_identifier(argument_type argument_identifier /* , ... */);
};
ArgumentNameKeyword ::
    attribute
    callback
    const
    constructor
    deleter
    dictionary
    enum
    getter
    includes
    inherit
    interface
    iterable
    maplike
    mixin
    namespace
    partial
    readonly
    required
    setlike
    setter
    static
    stringifier
    typedef
    unrestricted

identifier 토큰이 사용된 경우, 연산 인자의 식별자는 해당 토큰 값에서 앞의 U+005F (_)를 제거한 값입니다. 만약 ArgumentNameKeyword 키워드 토큰이 사용된다면, 연산 인자의 식별자는 그 토큰 자체입니다.

위에 언급된 IDL 구조(연산 인자 제외)의 식별자는 "constructor", "toString"이거나 U+005F (_)로 시작해서는 안 됩니다. 이런 것들은 예약 식별자라 부릅니다.

"toJSON" 식별자는 예약 식별자는 아니지만, 정상 연산에서만 객체를 JSON 타입으로 변환하는 목적으로 사용해야 하며, § 2.5.3.1 toJSON에서 설명합니다.

참고: 특정 구조에 대한 식별자 명명 제한은 이후 섹션에서 추가될 수 있습니다.

주어진 구현체가 지원하는 IDL 프래그먼트 집합 내에서, 모든 인터페이스, 네임스페이스, 딕셔너리, 열거형, 콜백 함수, 콜백 인터페이스인터페이스, 타입 정의의 식별자는 다른 인터페이스, 네임스페이스, 딕셔너리, 열거형, 콜백 함수, 콜백 인터페이스, 타입 정의의 식별자와 같아서는 안 됩니다.

하나의 IDL 프래그먼트 내에서는, 정의에 대한 참조가 참조된 정의의 선언 뒤에 등장하지 않아도 됩니다. 또한 IDL 프래그먼트 간에도 참조할 수 있습니다.

따라서, 아래의 IDL 프래그먼트는 유효합니다:

[Exposed=Window]
interface B : A {
  undefined f(SequenceOfLongs x);
};

[Exposed=Window]
interface A {
};

typedef sequence<long> SequenceOfLongs;

아래의 IDL 프래그먼트는 정의와 인터페이스 멤버에 어떻게 식별자가 부여되는지 보여줍니다.

// 타입 정의 식별자: "number"
typedef double number;

// 인터페이스 식별자: "System"
[Exposed=Window]
interface System {

  // 연산 식별자:          "createObject"
  // 연산 인자 식별자: "interface"
  object createObject(DOMString _interface);

  // 연산 인자 식별자: "interface"
  sequence<object> getObjects(DOMString interface);

  // 연산에는 식별자가 없음; getter 선언임.
  getter DOMString (DOMString keyName);
};

// 인터페이스 식별자: "TextField"
[Exposed=Window]
interface TextField {

  // 속성 식별자: "const"
  attribute boolean _const;

  // 속성 식별자: "value"
  attribute DOMString? _value;
};

TextField 인터페이스의 두 번째 속성은 (IDL 문법에서 "value"가 키워드가 아니므로) 반드시 밑줄로 이스케이프할 필요는 없지만, 그래도 속성의 식별자를 얻기 위해 언이스케이프됩니다.

2.2. 인터페이스

IDL 프래그먼트는 객체 지향 시스템을 기술하는 데 사용됩니다. 이러한 시스템에서 객체란 정체성을 가지고 있으며, 상태와 행동을 캡슐화한 엔티티입니다. 인터페이스는 (interface InterfaceRest에 일치) 해당 인터페이스를 구현하는 객체가 노출하는 상태와 행동을 선언하는 정의입니다.

[extended_attributes]
interface identifier {
  /* interface_members... */
};

인터페이스는 인터페이스 멤버 (InterfaceMembers에 일치)의 집합을 명세합니다. 인터페이스 선언 중괄호 사이에 등장하는 멤버들이 이에 해당합니다.

웹 IDL의 인터페이스는 해당 인터페이스를 구현하는 객체가 어떻게 동작하는지 기술합니다. 객체 지향 언어 바인딩에서는, 특정 IDL 인터페이스를 구현하는 객체가 객체의 상태를 검사하고 수정하며, 인터페이스가 기술하는 동작을 호출할 수 있도록 제공하는 것이 기대됩니다.

인터페이스는 다른 인터페이스를 상속하도록 정의할 수 있습니다. 만약 인터페이스 식별자 뒤에 U+003A (:)와 식별자가 오면, 해당 식별자가 상속받는 인터페이스를 나타냅니다. 어떤 객체가 다른 인터페이스를 상속한 인터페이스를 구현하면, 그 객체는 상속받은 인터페이스도 구현하게 됩니다. 즉, 객체는 상속된 인터페이스의 멤버도 가지게 됩니다.

interface identifier : identifier_of_inherited_interface {
  /* interface_members... */
};

멤버의 등장 순서는 자바스크립트 바인딩에서 프로퍼티 열거에 영향을 미칩니다.

인터페이스는 상속받은 인터페이스의 멤버와 같은 이름의 인터페이스 멤버를 명시할 수도 있습니다. 파생 인터페이스를 구현하는 객체는 파생 인터페이스의 멤버를 노출합니다. 오버라이드된 멤버를 객체에서 접근할 수 있는지는 언어 바인딩에 따라 다릅니다.

다음 두 개의 인터페이스를 살펴봅시다.

[Exposed=Window]
interface A {
  undefined f();
  undefined g();
};

[Exposed=Window]
interface B : A {
  undefined f();
  undefined g(DOMString x);
};

자바스크립트 바인딩에서 B의 인스턴스는 아래와 같은 프로토타입 체인을 가집니다:

[Object.prototype: Object 프로토타입 객체]
     ↑
[A.prototype: A의 인터페이스 프로토타입 객체]
     ↑
[B.prototype: B의 인터페이스 프로토타입 객체]
     ↑
[instanceOfB]

자바스크립트에서 instanceOfB.f()를 호출하면 B에 정의된 f가 실행됩니다. 하지만 A의 f도 A.prototype.f.call(instanceOfB)로 호출할 수 있습니다.

주어진 인터페이스 A의 상속 인터페이스들은 A가 직접 또는 간접적으로 상속하는 모든 인터페이스의 집합입니다. A가 다른 인터페이스를 상속하지 않으면 집합은 비어 있습니다. 그렇지 않으면, 집합에는 A가 상속하는 인터페이스 B와 B의 상속 인터페이스들이 포함됩니다.

인터페이스의 상속 계층에 순환(cycle)이 있어서는 안 됩니다. 즉, 인터페이스 A가 자기 자신을 상속하거나, B에서 A를 상속하는 등 반복적으로 상속할 수 없습니다.

리스트로서 포함된 상속 인터페이스들은 인터페이스 I에 대해 다음과 같이 정의됩니다:
  1. result를 « »로 둔다.

  2. interface를 I로 둔다.

  3. interface가 null이 아닐 동안:

    1. result에 interface를 추가한다.

    2. interface를 I가 상속하는 인터페이스로 설정하고, 없으면 null로 한다.

  4. result를 반환한다.

일반적인 인터페이스의 다중 상속은 지원하지 않으며, 객체도 임의의 인터페이스 집합을 구현할 수 없습니다. 객체는 하나의 주어진 인터페이스 A를 구현하도록 정의되며, 이는 A의 상속 인터페이스들도 구현함을 의미합니다. 추가로, includes 문을 사용하여 인터페이스 A를 구현하는 객체가 인터페이스 믹스인 멤버도 항상 포함하도록 정의할 수 있습니다. A가 include하는 인터페이스 믹스인의 멤버를 포함합니다.

각 인터페이스 멤버는 확장 속성 리스트(ExtendedAttributeList에 일치)가 앞에 올 수 있으며, 이는 해당 멤버가 언어 바인딩에서 어떻게 처리될지 제어합니다.

[extended_attributes]
interface identifier {

  [extended_attributes]
  const type constant_identifier = 42;

  [extended_attributes]
  attribute type identifier;

  [extended_attributes]
  return_type identifier(/* arguments... */);
};

인터페이스에 대한 IDL은 부분 인터페이스 정의(partial interface PartialInterfaceRest에 일치)를 사용하여 여러 부분으로 나눌 수 있습니다. 부분 인터페이스 정의의 식별자는 반드시 인터페이스 정의의 식별자와 같아야 합니다. 각 부분 인터페이스에 등장하는 모든 멤버는 실제 인터페이스의 멤버로 간주합니다.

interface SomeInterface {
  /* interface_members... */
};

partial interface SomeInterface {
  /* interface_members... */
};

참고: 부분 인터페이스 정의는 명세 편집 시, 하나의 인터페이스 정의를 여러 문서 또는 여러 섹션에 나눠서 기술하는 데 도움을 주기 위한 것입니다.

인터페이스 정의와 그 부분 인터페이스 정의의 등장 순서는 중요하지 않습니다.

참고: 부분 인터페이스 정의는 인터페이스가 다른 인터페이스를 상속하도록 지정할 수 없습니다. 상속은 원래의 인터페이스 정의에서 지정해야 합니다.

적용되는 언어 바인딩이 인터페이스가 해당 언어의 구조와 어떻게 대응되는지 결정합니다.

다음 확장 속성들이 인터페이스에 적용될 수 있습니다: [CrossOriginIsolated], [Exposed], [Global], [LegacyFactoryFunction], [LegacyNoInterfaceObject], [LegacyOverrideBuiltIns], [LegacyWindowAlias], [SecureContext].

다음 확장 속성들은 부분 인터페이스에 적용될 수 있습니다: [CrossOriginIsolated], [Exposed], [LegacyOverrideBuiltIns], [SecureContext].

인터페이스는 반드시 [Exposed] 확장 속성으로 주석 처리해야 합니다.

인터페이스 interface의 정규화된 이름은 다음과 같이 정의됩니다:

  1. identifier를 interface의 식별자로 둔다.

  2. interface에 [LegacyNamespace] 확장 속성이 있으면:

    1. namespace를 [LegacyNamespace] 확장 속성의 식별자 인자로 둔다.

    2. « namespace, identifier »를 U+002E (.)로 연결하여 반환한다.

  3. identifier를 반환한다.

CallbackOrInterfaceOrMixin ::
    callback CallbackRestOrInterface
    interface InterfaceOrMixin
InterfaceOrMixin ::
    InterfaceRest
    MixinRest
InterfaceRest ::
    identifier Inheritance { InterfaceMembers } ;
Partial ::
    partial PartialDefinition
PartialDefinition ::
    interface PartialInterfaceOrPartialMixin
    PartialDictionary
    Namespace
PartialInterfaceOrPartialMixin ::
    PartialInterfaceRest
    MixinRest
PartialInterfaceRest ::
    identifier { PartialInterfaceMembers } ;
InterfaceMembers ::
    ExtendedAttributeList InterfaceMember InterfaceMembers
    ε
InterfaceMember ::
    PartialInterfaceMember
    Constructor
PartialInterfaceMembers ::
    ExtendedAttributeList PartialInterfaceMember PartialInterfaceMembers
    ε
PartialInterfaceMember ::
    Const
    Operation
    Stringifier
    StaticMember
    Iterable
    AsyncIterable
    ReadOnlyMember
    ReadWriteAttribute
    ReadWriteMaplike
    ReadWriteSetlike
    InheritAttribute
Inheritance ::
    : identifier
    ε

아래 IDL 프래그먼트는 상호 참조하는 두 인터페이스의 정의를 보여줍니다. Human과 Dog는 모두 Animal을 상속합니다. 이 두 인터페이스를 구현하는 객체는 name 속성을 갖게 됩니다.

[Exposed=Window]
interface Animal {
  attribute DOMString name;
};

[Exposed=Window]
interface Human : Animal {
  attribute Dog? pet;
};

[Exposed=Window]
interface Dog : Animal {
  attribute Human? owner;
};

아래 IDL 프래그먼트는 DOM 인터페이스와 콜백 인터페이스의 단순화된 정의를 보여줍니다.

[Exposed=Window]
interface Node {
  readonly attribute DOMString nodeName;
  readonly attribute Node? parentNode;
  Node appendChild(Node newChild);
  undefined addEventListener(DOMString type, EventListener listener);
};

callback interface EventListener {
  undefined handleEvent(Event event);
};

일반 객체는 EventListener와 같은 콜백 인터페이스를 구현할 수 있습니다:

var node = getNode();                                // Node 인스턴스 얻기

var listener = {
  handleEvent: function(event) {
    // ...
  }
};
node.addEventListener("click", listener);            // 동작함

node.addEventListener("click", function() { ... });  // 이것도 동작함

이런 객체는 Node와 같은 인터페이스를 구현할 수는 없습니다:

var node = getNode();  // Node 인스턴스 얻기

var newNode = {
  nodeName: "span",
  parentNode: null,
  appendChild: function(newchild) {
    // ...
  },
  addEventListener: function(type, listener) {
    // ...
  }
};
node.appendChild(newNode);  // TypeError 예외 발생

2.3. 인터페이스 믹스인

인터페이스 믹스인은 (interface MixinRest에 일치) 하나 이상의 인터페이스에서 include하여 객체가 노출할 수 있는 상태와 행동을 선언합니다. 인터페이스에서 include한 인터페이스 믹스인을 구현하는 객체에 의해 노출됩니다.

interface mixin identifier {
  /* mixin_members... */
};

참고: 인터페이스 믹스인은 부분 인터페이스와 마찬가지로, 명세 편집의 편의를 위해 사용되어 일관된 기능 집합을 묶고, 여러 인터페이스(문서 간 포함 가능)에 포함할 수 있게 합니다. 언어 바인딩을 통해 직접 노출되도록 의도된 것이 아닙니다. § 2.3.1 믹스인 및 부분 사용에서 부분 인터페이스, 인터페이스 믹스인, 부분 인터페이스 믹스인 중 어느 것을 선택할지 설명합니다.

인터페이스 믹스인은 인터페이스 믹스인 멤버 (MixinMembers에 일치) 집합을 명세합니다. 즉, 상수, 일반 연산, 일반 속성, 문자열 변환자들이 해당 인터페이스 믹스인 선언의 중괄호 사이에 선언됩니다.

이러한 상수 , 일반 연산 , 일반 속성 , 문자열 변환자 는 객체가 구현할 수 있는 동작을 기술하며, 마치 이를 포함하는 인터페이스 에 직접 명세한 것처럼 동작합니다.

정적 속성, 정적 연산, 특수 연산, 이터러블, 비동기 이터러블, maplike, setlike 선언은 인터페이스 믹스인 선언에 포함될 수 없습니다.

인터페이스와 마찬가지로, 인터페이스 믹스인의 IDL도 부분 인터페이스 믹스인 정의(partial interface MixinRest에 일치)를 이용해 여러 부분으로 나눌 수 있습니다. 부분 인터페이스 믹스인 정의의 식별자는 해당 인터페이스 믹스인 정의의 식별자와 같아야 합니다. 각 부분 인터페이스 믹스인에 등장하는 모든 멤버는 실제 인터페이스 믹스인의 멤버로 간주되고, 인터페이스가 include하는 인터페이스 믹스인을 통해 해당 인터페이스의 멤버로도 간주됩니다.

interface mixin SomeMixin {
  /* mixin_members... */
};

partial interface mixin SomeMixin {
  /* mixin_members... */
};

멤버의 등장 순서는 자바스크립트 바인딩에서 프로퍼티 열거에 영향을 줍니다.

인터페이스나 딕셔너리와 달리, 인터페이스 믹스인은 타입을 생성하지 않습니다.

이 명세에서 정의된 확장 속성 중, [CrossOriginIsolated], [Exposed], [SecureContext] 만 인터페이스 믹스인에 적용됩니다.

includes 문은 (IncludesStatement에 일치) 모든 인터페이스 I (첫 번째 식별자로 식별됨)를 구현하는 객체가 멤버를 인터페이스 믹스인 M (두 번째 식별자로 식별됨)의 멤버를 추가로 포함해야 함을 선언하는 정의입니다. 인터페이스 I는 include 인터페이스 믹스인 M을 포함한다고 합니다.

interface_identifier includes mixin_identifier;

첫 번째 식별자는 인터페이스 I를 참조해야 하며, 두 번째 식별자는 인터페이스 믹스인 M을 참조해야 합니다.

M의 각 멤버는 인터페이스 I, J, K 등 include하는 모든 인터페이스의 멤버로 간주됩니다. 즉, M의 멤버 m에 대해 I는 멤버 mI, J는 멤버 mJ, K는 멤버 mK를 갖게 됩니다. 호스트 인터페이스란 mI, mJ, mK의 각각의 I, J, K를 말합니다.

참고: 자바스크립트에서는, 인터페이스 믹스인 멤버로 선언된 일반 연산이 내장 함수 객체 값의 데이터 속성으로 노출될 때, 연결된 인터페이스가 M을 포함하는 각 인터페이스 프로토타입 객체마다 별도 내장 함수 객체가 생성됩니다. 속성도 마찬가지로 접근자 속성의 getter와 setter가 각각 별도 내장 함수 객체가 됩니다.

includes 문의 등장 순서는 호스트 인터페이스에서 인터페이스 믹스인이 포함되는 순서에 영향을 줍니다.

멤버 순서는 명확히 규정되어 있지 않으며, 특히 인터페이스 믹스인이 별도 문서에 정의될 때 더욱 그렇습니다. issue #432에서 논의되고 있습니다.

이 명세에서 정의된 확장 속성 중 includes 문에 적용 가능한 것은 없습니다.

아래 IDL 프래그먼트는 인터페이스 Entry와 인터페이스 믹스인 Observable의 정의를 보여줍니다. includes 문은 Observable의 멤버들이 Entry를 구현하는 모든 객체에 항상 포함된다는 것을 명시합니다.

interface Entry {
  readonly attribute unsigned short entryType;
  // ...
};

interface mixin Observable {
  undefined addEventListener(DOMString type,
                        EventListener listener,
                        boolean useCapture);
  // ...
};

Entry includes Observable;

자바스크립트 구현에서는 모든 Entry의 프로토타입 체인에 addEventListener 속성이 있게 됩니다:

var e = getEntry();          // Entry 인스턴스 얻기
typeof e.addEventListener;   // "function"으로 평가됨
CallbackOrInterfaceOrMixin ::
    callback CallbackRestOrInterface
    interface InterfaceOrMixin
InterfaceOrMixin ::
    InterfaceRest
    MixinRest
Partial ::
    partial PartialDefinition
PartialDefinition ::
    interface PartialInterfaceOrPartialMixin
    PartialDictionary
    Namespace
MixinRest ::
    mixin identifier { MixinMembers } ;
MixinMembers ::
    ExtendedAttributeList MixinMember MixinMembers
    ε
MixinMember ::
    Const
    RegularOperation
    Stringifier
    OptionalReadOnly AttributeRest
IncludesStatement ::
    identifier includes identifier ;

2.3.1. 믹스인 및 부분 사용

이 섹션은 참고용입니다.

인터페이스 믹스인은 속성, 상수, 연산을 여러 인터페이스에 공유할 수 있게 해줍니다. 만약 하나의 인터페이스만 확장하려는 경우라면 부분 인터페이스 사용을 고려할 수 있습니다.

예를 들면, 다음과 같이 하지 말고:

interface mixin WindowSessionStorage {
  readonly attribute Storage sessionStorage;
};
Window includes WindowSessionStorage;

이렇게 하세요:

partial interface Window {
  readonly attribute Storage sessionStorage;
};

또한, 다른 명세에서 노출하는 인터페이스 믹스인을 확장하여 window와 worker 등 여러 컨텍스트에 속성, 상수, 연산을 노출하는 등 공통적인 활용 사례를 타겟할 수도 있습니다.

예를 들어, 흔하지만 장황한 방식 대신:

interface mixin GlobalCrypto {
  readonly attribute Crypto crypto;
};

Window includes GlobalCrypto;
WorkerGlobalScope includes GlobalCrypto;

WindowOrWorkerGlobalScope 인터페이스 믹스인을 부분 인터페이스 믹스인으로 확장할 수 있습니다:

partial interface mixin WindowOrWorkerGlobalScope {
  readonly attribute Crypto crypto;
};

2.4. 콜백 인터페이스

콜백 인터페이스는 정의로, callback interface identifier { CallbackInterfaceMembers } ;에 일치합니다. § 2.12 인터페이스를 구현하는 객체에서 설명한 대로, 어떤 객체든 구현할 수 있습니다.

참고: 콜백 인터페이스는 인터페이스가 아닙니다. 명칭과 문법은 표준의 이전 버전에서 유래된 것으로, 당시에는 개념적으로 더 많은 공통점이 있었습니다.

콜백 인터페이스는 콜백 인터페이스 멤버 (CallbackInterfaceMembers에 일치)의 집합을 명세합니다. 이들은 인터페이스 선언의 중괄호 사이에 등장하는 멤버입니다.

callback interface identifier {
  /* interface_members... */
};

참고: 유사한 명칭의 콜백 함수 정의도 참고하세요.

콜백 인터페이스는 정확히 하나의 일반 연산을 정의해야 합니다.

명세 저자는 콜백 인터페이스를 기존 API의 요구사항을 기술할 필요가 없는 한 정의하지 않아야 합니다. 대신 콜백 함수를 사용하는 것이 좋습니다.

EventListener 를 콜백 인터페이스로 정의한 것은, 특정 속성(여기서는 handleEvent)을 가진 객체가 해당 인터페이스를 구현한 것으로 간주될 수 있도록 해야 하는 기존 API의 예입니다. 새로운 API나 호환성 문제가 없는 경우에는, 콜백 함수를 사용하면 자바스크립트 바인딩에서 함수 객체만 허용됩니다.

콜백 인터페이스가 상수를 선언하는 경우 반드시 [Exposed] 확장 속성으로 주석 처리해야 합니다.

CallbackRestOrInterface ::
    CallbackRest
    interface identifier { CallbackInterfaceMembers } ;
CallbackInterfaceMembers ::
    ExtendedAttributeList CallbackInterfaceMember CallbackInterfaceMembers
    ε
CallbackInterfaceMember ::
    Const
    RegularOperation

2.5. 멤버

인터페이스, 인터페이스 믹스인, 네임스페이스는 중괄호 안에 등장하는 멤버(각각 InterfaceMembers, MixinMembers, NamespaceMembers에 일치)을 명세합니다. 멤버에는 상수, 속성, 연산, 기타 선언이 있습니다. 속성은 해당 인터페이스, 인터페이스 믹스인, 네임스페이스를 구현하는 객체가 노출하는 상태를 설명하며, 연산은 객체에서 호출할 수 있는 동작을 설명합니다. 상수는 시스템 내 객체 사용자에게 편의를 제공하기 위한 이름 있는 상수 값을 선언합니다.

어떤 인터페이스가 인터페이스 믹스인을 include하면, 해당 인터페이스 믹스인의 멤버들도 인터페이스의 멤버로 간주됩니다. 반면, 상속받은 인터페이스 멤버는 해당 인터페이스의 멤버로 간주하지 않습니다.

여러 멤버에 대해 정의되는 생성자 단계, getter 단계, setter 단계, 메서드 단계는 해당 인터페이스 또는 인터페이스 믹스인 위에 정의된 멤버에서 this 값을 사용할 수 있습니다. 이는 멤버가 선언된 인터페이스 타입, 혹은 멤버가 선언된 인터페이스 믹스인을 include한 타입의 IDL 값입니다.

setter 단계에서는 지정된 값도 사용할 수 있는데, 이는 해당 속성이 선언된 타입의 IDL 값입니다.

인터페이스, 인터페이스 믹스인, 콜백 인터페이스, 네임스페이스는 각각 지원하는 멤버의 종류가 다르며, § 2.2 인터페이스, § 2.3 인터페이스 믹스인, § 2.4 콜백 인터페이스, § 2.6 네임스페이스에서 설명합니다. 아래 표는 이를 요약한 참고용 표입니다:

인터페이스 콜백 인터페이스 인터페이스 믹스인 네임스페이스
상수 ● ● ●
일반 속성 ● ● 오직 읽기 전용 속성만
정적 속성 ●
일반 연산 ● ● ● ●
문자열 변환자 ● ●
특수 연산 ●
정적 연산 ●
이터러블 선언 ●
비동기 이터러블 선언 ●
maplike 선언 ●
setlike 선언 ●

2.5.1. 상수

상수는 (Const에 일치) 이름에 상수값을 바인딩하는 선언입니다. 상수는 인터페이스와 콜백 인터페이스에 등장할 수 있습니다.

상수는 과거에 주로 열거형 스타일로 명명된 정수 코드를 정의하는 데 사용되었습니다. 웹 플랫폼은 문자열 사용으로 이 패턴에서 벗어나고 있습니다. 이 기능을 사용하려는 편집자는 진행하기 전에 이슈를 등록하여 논의할 것을 강력히 권고합니다.

const type constant_identifier = 42;

상수의 식별자는 동일한 인터페이스 멤버 또는 콜백 인터페이스 멤버의 식별자와 같아서는 안 됩니다(동일한 인터페이스나 콜백 인터페이스에 정의된). 또한 "length", "name", "prototype"이어서는 안 됩니다.

참고: 이 세 이름은 자바스크립트 바인딩에서 인터페이스 객체에 정의된 프로퍼티 이름입니다.

상수의 타입(ConstType에 일치)은 원시 타입이어야 하며, 그 외 타입은 허용되지 않습니다. 식별자가 사용되는 경우, 해당 식별자는 원시 타입인 타입 정의를 참조해야 합니다.

상수 선언의 ConstValue 부분은 상수의 값을 나타내며, 두 개의 불리언 리터럴 토큰(true, false), integer 토큰, decimal 토큰, 또는 세 가지 특수 부동소수점 상수값(-Infinity, Infinity, NaN) 중 하나일 수 있습니다.

참고: 이 값들은(문자열, 빈 시퀀스 포함) 딕셔너리 멤버의 기본값이나 옵션 인자 기본값으로도 사용할 수 있습니다. 단, 문자열, 빈 시퀀스 [], 기본 딕셔너리 {}는 상수의 값으로 사용할 수 없습니다.

불리언 리터럴 토큰 true와 false의 값은 IDL boolean 타입의 true와 false입니다.

integer 토큰의 값은 다음과 같이 결정된 정수입니다:

  1. S를 integer 토큰에 일치하는 스칼라 값의 시퀀스로 둡니다.

  2. S가 U+002D(-)로 시작하면 sign는 −1, 그렇지 않으면 1입니다.

  3. 선택적 U+002D(-) 뒤의 스칼라 값에 따라 base를 결정합니다:

    U+0030 (0), U+0058 (X)
    U+0030 (0), U+0078 (x)

    base는 16입니다.

    U+0030 (0)

    base는 8입니다.

    기타

    base는 10입니다.

  4. 선택적인 맨 앞 U+002D (-) 문자와 진법을 나타내는 스칼라 값 뒤에 남은 모든 스칼라 값 을 base 진법 정수로 해석한 결과를 number 로 둡니다.

  5. sign × number를 반환합니다.

integer 토큰의 타입은 사용되는 상수, 딕셔너리 멤버, 옵션 인자의 타입과 동일합니다. 해당 토큰의 값은 § 2.13 타입에서 주어진 타입의 유효 범위를 벗어나면 안 됩니다.

decimal 토큰의 값은, 해당 상수, 딕셔너리 멤버, 옵션 인자가 float, unrestricted float, double, unrestricted double 타입 중 무엇인지에 따라 IEEE 754 단정밀도 또는 배정밀도 부동소수점 숫자가 됩니다:
  1. S를 decimal 토큰에 일치하는 스칼라 값의 시퀀스로 둡니다.

  2. S를 자바스크립트 NumericLiteral로 파싱했을 때의 수학적 값을 result로 둡니다.

  3. 해당 토큰이 float 또는 unrestricted float의 값으로 사용되면, result에 가장 가까운 IEEE 754 단정밀도 부동소수점 숫자가 값입니다.

  4. 그 외에는 double 또는 unrestricted double의 값으로 사용되며, result에 가장 가까운 IEEE 754 배정밀도 부동소수점 숫자가 값입니다. [IEEE-754]

상수값이 Infinity, -Infinity, NaN로 지정된 경우, 상수, 딕셔너리 멤버, 옵션 인자의 타입에 따라 IEEE 754 단정밀도 또는 배정밀도 부동소수점 숫자가 됩니다:

타입 unrestricted float, 상수값 Infinity

값은 IEEE 754 단정밀도 양의 무한대입니다.

타입 unrestricted double, 상수값 Infinity

값은 IEEE 754 배정밀도 양의 무한대입니다.

타입 unrestricted float, 상수값 -Infinity

값은 IEEE 754 단정밀도 음의 무한대입니다.

타입 unrestricted double, 상수값 -Infinity

값은 IEEE 754 배정밀도 음의 무한대입니다.

타입 unrestricted float, 상수값 NaN

값은 비트 패턴 0x7fc00000의 IEEE 754 단정밀도 NaN입니다.

타입 unrestricted double, 상수값 NaN

값은 비트 패턴 0x7ff8000000000000의 IEEE 754 배정밀도 NaN입니다.

decimal 토큰의 타입은 사용되는 상수, 딕셔너리 멤버, 옵션 인자의 타입과 동일합니다. 해당 토큰의 값은 § 2.13 타입에서 주어진 타입의 유효 범위를 벗어나면 안 됩니다. 또한, Infinity, -Infinity, NaN은 float나 double 타입의 값으로 사용할 수 없습니다.

null 토큰의 값은 null 값이며, 널 허용 타입의 멤버입니다. null 토큰의 타입은 해당 상수, 딕셔너리 멤버, 옵션 인자의 타입과 동일합니다.

상수에 할당된 값의 타입 VT와 상수, 딕셔너리 멤버, 옵션 인자 자체의 타입 DT는 호환되어야 하며, DT와 VT가 동일하거나, DT가 널 허용 타입이고 내부 타입이 VT인 경우에 해당합니다.

상수는 해당 인터페이스 또는 콜백 인터페이스의 특정 인스턴스와 연결되지 않습니다. 인스턴스에서 상수가 노출되는지 여부는 언어 바인딩에 따라 다릅니다.

자바스크립트 바인딩에서는 그 상수가 선언된 IDL 인터페이스를 구현하는 객체를 통해 상수에 접근할 수 있습니다. 예를 들어, 다음과 같은 IDL에서:

[Exposed=Window]
interface A {
  const short rambaldi = 47;
};

상수값은 자바스크립트에서 A.rambaldi 또는 instanceOfA.rambaldi로 접근할 수 있습니다.

상수에 적용 가능한 확장 속성은 다음과 같습니다: [CrossOriginIsolated], [Exposed], [SecureContext].

Const ::
    const ConstType identifier = ConstValue ;
ConstValue ::
    BooleanLiteral
    FloatLiteral
    integer
BooleanLiteral ::
    true
    false
FloatLiteral ::
    decimal
    -Infinity
    Infinity
    NaN
ConstType ::
    PrimitiveType
    identifier

아래 IDL 프래그먼트는 위의 타입의 상수가 어떻게 정의될 수 있는지 보여줍니다.

[Exposed=Window]
interface Util {
  const boolean DEBUG = false;
  const octet LF = 10;
  const unsigned long BIT_MASK = 0x0000fc00;
  const double AVOGADRO = 6.022e23;
};

2.5.2. 속성

속성은 인터페이스 멤버 또는 네임스페이스 멤버로, (inherit AttributeRest, static OptionalReadOnly AttributeRest, stringifier OptionalReadOnly AttributeRest, OptionalReadOnly AttributeRest, 또는 AttributeRest에 일치) 주어진 타입과 식별자를 가진 데이터 필드를 선언하며, 해당 값은 조회되거나(일부 경우) 변경될 수 있습니다. 속성에는 두 가지 종류가 있습니다:

  1. 일반 속성은 해당 인터페이스를 구현하는 객체가 지정된 식별자의 데이터 필드 멤버를 갖도록 선언합니다.

    interface interface_identifier {
      attribute type identifier;
    };
    
  2. 정적 속성은 인터페이스를 구현하는 특정 객체와 관련되지 않은 속성을 선언할 때 사용합니다.

    interface interface_identifier {
      static attribute type identifier;
    };
    

속성에 static 키워드가 없으면 일반 속성을 선언한 것이고, 있으면 정적 속성을 선언한 것입니다. 참고로 인터페이스 멤버 외에도, 읽기 전용 일반 속성은 네임스페이스 멤버가 될 수도 있습니다.

속성 attr의 getter 단계는 “attr getter 단계는 다음과 같다:”(목록) 또는 “attr getter 단계는 다음을 수행한다”(인라인 설명)와 같은 텍스트로 소개해야 합니다.

속성 attr의 setter 단계는 “attr setter 단계는 다음과 같다:”(목록) 또는 “attr setter 단계는 다음을 수행한다”(인라인 설명)와 같은 텍스트로 소개해야 합니다.

참고: getter 단계를 정의할 때는 this에 암묵적으로 접근할 수 있습니다. setter 단계를 정의할 때는 this와 지정된 값에 암묵적으로 접근할 수 있습니다.

속성의 식별자는 동일한 인터페이스에 정의된 다른 인터페이스 멤버의 식별자와 같아서는 안 됩니다. 정적 속성의 식별자는 "prototype"이면 안 됩니다.

속성의 타입은 attribute 키워드 뒤에 등장하는 타입(Type에 일치)으로 정해집니다. 만약 Type이 식별자거나 식별자 다음에 ?가 붙은 경우, 해당 식별자는 인터페이스, 열거형, 콜백 함수, 콜백 인터페이스, 타입 정의를 식별해야 합니다.

타입 정의를 해석한 후, 속성의 타입은 다음 타입의 널 허용 또는 비허용 버전이 되어서는 안 됩니다:

속성은 읽기 전용이며, readonly 키워드가 attribute 키워드 앞에 있으면 그렇게 됩니다. 읽기 전용 속성이 정의된 인터페이스를 구현하는 객체는 해당 속성에 값을 할당할 수 없습니다. 언어 바인딩마다 할당이 단순히 금지되는지, 무시되는지, 예외가 발생하는지 다를 수 있습니다.

interface interface_identifier {
  readonly attribute type identifier;
};

타입이 프라미스 타입인 속성은 반드시 읽기 전용이어야 하며, 또한 [LegacyLenientSetter], [PutForwards], [Replaceable], [SameObject] 확장 속성을 가질 수 없습니다.

읽기 전용이 아닌 일반 속성은 상위 인터페이스에서 getter를 상속받도록 선언할 수 있습니다. 이를 통해 상위 인터페이스의 읽기 전용 속성을 파생 인터페이스에서 쓰기 가능하게 만들 수 있습니다. 속성이 getter를 상속하려면 선언에 inherit이 포함되어야 합니다. getter를 상속받는 속성은 가장 가까운 상위 인터페이스에서 동일한 식별자를 가진 속성입니다. getter를 상속받는 속성과 상속하는 속성의 타입은 같아야 합니다.

참고: 문법상 inherit는 읽기 전용 속성이나 정적 속성에 사용할 수 없습니다.

[Exposed=Window]
interface Ancestor {
  readonly attribute TheType theIdentifier;
};

[Exposed=Window]
interface Derived : Ancestor {
  inherit attribute TheType theIdentifier;
};

stringifier 키워드가 일반 속성 선언에 사용되면, 해당 인터페이스를 구현하는 객체가 해당 속성 값으로 문자열 변환됨을 의미합니다. 자세한 내용은 § 2.5.5 문자열 변환자를 참조하세요.

interface interface_identifier {
  stringifier attribute DOMString identifier;
};

다음 확장 속성은 일반 및 정적 속성에 적용 가능합니다: [CrossOriginIsolated], [Exposed], [SameObject], [SecureContext].

다음 확장 속성은 일반 속성에만 적용됩니다: [LegacyLenientSetter], [LegacyLenientThis], [PutForwards], [Replaceable], [LegacyUnforgeable].

ReadOnlyMember ::
    readonly ReadOnlyMemberRest
ReadOnlyMemberRest ::
    AttributeRest
    MaplikeRest
    SetlikeRest
ReadWriteAttribute ::
    AttributeRest
InheritAttribute ::
    inherit AttributeRest
AttributeRest ::
    attribute TypeWithExtendedAttributes AttributeName ;
AttributeName ::
    AttributeNameKeyword
    identifier
AttributeNameKeyword ::
    required
OptionalReadOnly ::
    readonly
    ε

아래 IDL 프래그먼트는 인터페이스에 속성을 선언하는 방법을 보여줍니다:

[Exposed=Window]
interface Animal {

  // 임의의 문자열 값으로 설정 가능한 단순 속성.
  readonly attribute DOMString name;

  // 값을 할당할 수 있는 속성.
  attribute unsigned short age;
};

[Exposed=Window]
interface Person : Animal {

  // Animal에서 getter 동작을 상속받으며, Person 설명에서 별도 명시 필요 없음.
  inherit attribute DOMString name;
};

2.5.3. 연산

연산은 인터페이스 멤버, 콜백 인터페이스 멤버, 네임스페이스 멤버 (static RegularOperation, stringifier, RegularOperation 또는 SpecialOperation에 일치) 해당 인터페이스를 구현하는 객체에서 호출할 수 있는 동작을 정의합니다. 연산에는 세 가지 종류가 있습니다:

  1. 일반 연산은 해당 인터페이스를 구현하는 객체가 지정된 식별자의 메서드를 갖도록 선언합니다.

    interface interface_identifier {
      return_type identifier(/* arguments... */);
    };
    
  2. 특수 연산은 객체 인덱싱, 문자열 변환 등 특별한 동작을 구현하는 객체에 선언할 때 사용합니다.

    interface interface_identifier {
      /* special_keyword */ return_type identifier(/* arguments... */);
      /* special_keyword */ return_type (/* arguments... */);
    };
    
  3. 정적 연산은 인터페이스를 구현하는 특정 객체와 관련되지 않은 연산을 선언할 때 사용합니다.

    interface interface_identifier {
      static return_type identifier(/* arguments... */);
    };
    

연산에 식별자가 있고 static 키워드가 없으면 일반 연산을 선언한 것입니다. 연산에 선언에 특수 키워드(Special에 일치하는 키워드 또는 stringifier 키워드)가 있으면 특수 연산을 선언합니다. 하나의 연산이 일반 연산과 특수 연산을 동시에 선언할 수도 있습니다. 자세한 내용은 § 2.5.6 특수 연산을 참조하세요. 참고로, 일반 연산은 인터페이스 멤버 외에도, 콜백 인터페이스 멤버 및 네임스페이스 멤버가 될 수 있습니다.

연산에 식별자가 없으면 반드시 특수 키워드를 사용하여 특수 연산으로 선언해야 합니다.

일반 연산 또는 정적 연산의 식별자는 동일한 인터페이스, 콜백 인터페이스, 네임스페이스에 정의된 상수나 속성의 식별자와 같아서는 안 됩니다. 정적 연산의 식별자는 "prototype"이면 안 됩니다.

참고: 연산의 식별자는 동일 인터페이스의 다른 연산과 같을 수 있습니다. 이는 연산 오버로딩을 명세하는 방식입니다.

참고: 정적 연산의 식별자는 동일 인터페이스에 정의된 일반 연산의 식별자와 같을 수 있습니다.

연산의 반환 타입은 연산 선언에서 식별자 앞에 등장하는 타입(Type에 일치)으로 정해집니다. 반환 타입이 ?가 붙은 식별자인 경우, 해당 식별자는 인터페이스, 딕셔너리, 열거형, 콜백 함수, 콜백 인터페이스, 타입 정의를 식별해야 합니다.

연산의 인자(ArgumentList에 일치)는 선언의 괄호 사이에 명시됩니다. 각 인자는 타입(Type에 일치) 뒤에 식별자(ArgumentName에 일치)로 지정합니다.

참고: 표현력을 위해, 연산 인자의 식별자는 ArgumentNameKeyword 심볼에 일치하는 키워드 중 하나로 지정할 수 있으며, 이 경우 이스케이프할 필요가 없습니다.

연산 인자의 Type이 ?가 붙은 식별자인 경우, 해당 식별자는 인터페이스, 열거형, 콜백 함수, 콜백 인터페이스, 타입 정의를 식별해야 합니다. ?가 없는 식별자 타입인 경우, 해당 식별자는 위의 정의들 중 하나 또는 딕셔너리를 식별해야 합니다.

인자 타입을 타입 정의 해석 후, 널 허용 타입(nullable type)이면, 그 내부 타입은 딕셔너리 타입일 수 없습니다.

interface interface_identifier {
  return_type identifier(type identifier, type identifier /* , ... */);
};

각 인자의 식별자는 동일 연산 선언 내의 다른 인자 식별자와 같아서는 안 됩니다.

각 인자는 확장 속성 리스트(ExtendedAttributeList에 일치)가 앞에 올 수 있으며, 이는 해당 인자 값이 언어 바인딩에서 어떻게 처리되는지 제어합니다.

interface interface_identifier {
  return_type identifier([extended_attributes] type identifier, [extended_attributes] type identifier /* , ... */);
};

아래 IDL 프래그먼트는 인터페이스에 일반 연산을 선언하는 방법을 보여줍니다:

[Exposed=Window]
interface Dimensions {
  attribute unsigned long width;
  attribute unsigned long height;
};

[Exposed=Window]
interface Button {

  // 인자를 받지 않고 불리언을 반환하는 연산.
  boolean isMouseOver();

  // 오버로딩된 연산들.
  undefined setDimensions(Dimensions size);
  undefined setDimensions(unsigned long width, unsigned long height);
};

연산 또는 생성자 연산은 마지막 인자가 ... 토큰으로 선언된 경우 가변 인자로 간주됩니다. 가변 인자 연산은 마지막 인자 이후 임의 개수의 인자를 받아 호출할 수 있음을 의미합니다. 추가 암시적 형식 인자들은 연산 선언의 마지막 명시적 인자와 동일한 타입입니다. 마지막 인자는 연산 호출 시 생략할 수도 있습니다. ... 토큰은 반드시 연산 인자 리스트의 마지막 인자에만 사용할 수 있습니다.

interface interface_identifier {
  return_type identifier(type... identifier);
  return_type identifier(type identifier, type... identifier);
};

확장 속성 중 인자 리스트를 받는 ([LegacyFactoryFunction]) 및 콜백 함수도 ... 토큰이 인자 리스트에 사용되면 가변 인자로 간주합니다.

아래 IDL 프래그먼트는 두 개의 가변 인자 연산을 가진 인터페이스를 정의합니다:

[Exposed=Window]
interface IntegerSet {
  readonly attribute unsigned long cardinality;

  undefined union(long... ints);
  undefined intersection(long... ints);
};

자바스크립트 바인딩에서 가변 인자 연산은 추가 인자를 받을 수 있는 함수로 구현됩니다:

var s = getIntegerSet();  // IntegerSet 인스턴스 얻기

s.union();                // 'ints'에 해당하는 인자를 안 넘김
s.union(1, 4, 7);         // 'ints'에 해당하는 인자를 세 개 넘김

가변 인자 함수를 지원하지 않는 언어 바인딩에서는 명시적으로 배열이나 리스트를 인자로 넘기도록 명세할 수 있습니다.

인자에 optional 키워드가 있으면 옵션 인자로 간주합니다. 가변 인자(variadic) 연산의 마지막 인자도 옵션 인자로 간주됩니다. 인자를 옵션으로 선언하면 연산 호출 시 해당 인자를 생략할 수 있습니다. 연산이 가변 인자일 때 마지막 인자는 명시적으로 옵션 인자로 선언할 수 없습니다.

interface interface_identifier {
  return_type identifier(type identifier, optional type identifier);
};

옵션 인자는 기본값도 가질 수 있습니다. 인자 식별자 뒤에 U+003D(=)와 값(DefaultValue에 일치)이 오면, 그 값이 옵션 인자의 기본값이 됩니다. 가변 인자 연산의 마지막(암시적 옵션) 인자에는 기본값을 지정할 수 없습니다. 기본값은 해당 인자가 생략되어 호출될 때 적용됩니다.

interface interface_identifier {
  return_type identifier(type identifier, optional type identifier = "value");
};

boolean 타입의 옵션 인자에 true를 기본값으로 사용하는 것은 권장하지 않습니다. 저자는 기본 변환(즉 undefined → false)을 예상할 수 있으므로 혼동을 줄 수 있습니다. [API-DESIGN-PRINCIPLES]

인자 타입이 딕셔너리 타입 또는 유니온 타입 중 평탄화된 멤버 타입의 하나로 딕셔너리 타입을 갖는 타입이며, 해당 딕셔너리 타입 및 조상에 필수 멤버가 없고, 인자가 마지막이거나 뒤따르는 인자들이 모두 옵션 인자라면, 해당 인자는 옵션으로 선언되고 기본값을 지정해야 합니다.

이는 API 설계시 사용자가 딕셔너리의 기본값만 사용하고 싶을 때 빈 딕셔너리 값을 굳이 넘기지 않아도 되도록 하기 위함입니다.

대개 기본값으로 {}를 사용하지만, 유니온 타입에서 딕셔너리가 평탄화된 멤버 타입 중 하나라면 다른 멤버 초기화용 기본값을 지정할 수도 있습니다.

불리언 리터럴 토큰(true, false), null 토큰, integer 토큰, decimal 토큰, Infinity, -Infinity, NaN 중 하나가 옵션 인자 기본값으로 사용되면, 상수에 대해와 동일하게 해석합니다.

undefined 토큰이 옵션 인자 기본값으로 사용된 경우, 값은 IDL undefined입니다.

옵션 인자 기본값은 string 토큰으로도 지정할 수 있습니다. 값은 아래와 같이 문자열 타입으로 결정됩니다:
  1. S를 string 토큰에서 양끝 U+0022(") 스칼라 값을 제거한 후 남은 스칼라 값 시퀀스로 둡니다.

  2. 인자 타입에 따라:

    DOMString
    USVString
    열거형 타입

    string 토큰의 값은 S입니다.

    ByteString

    단, S에는 U+00FF를 초과하는 코드 포인트가 없어야 합니다.

    string 토큰의 값은 동형 인코딩된 S입니다.

옵션 인자의 타입이 열거형이면, 지정된 기본값은 반드시 해당 열거형 값 중 하나여야 합니다.

옵션 인자 기본값으로 두 토큰 값 []를 사용할 수 있으며, 이는 빈 시퀀스 값을 나타냅니다. 타입은 해당 옵션 인자의 타입과 동일해야 하며, 반드시 시퀀스 타입, 널 허용 타입 중 내부 타입이 시퀀스 타입인 것, 유니온 타입, 널 허용 유니온 타입은 시퀀스 타입을 평탄화된 멤버 타입 중 하나로 가져야 합니다.

옵션 인자 기본값으로 두 토큰 값 {}도 사용할 수 있으며, 이는 기본 초기화된(ES null 또는 속성이 없는 객체와 같이) 딕셔너리 값을 의미합니다. 타입은 해당 옵션 인자의 타입과 동일해야 하며, 반드시 딕셔너리 타입이거나 유니온 타입 중 딕셔너리 타입을 평탄화된 멤버 타입 중 하나로 가져야 합니다.

아래 IDL 프래그먼트는 두 가지 인자 리스트 길이로 호출 가능한 단일 연산을 가진 인터페이스를 정의합니다:

[Exposed=Window]
interface ColorCreator {
  object createColor(double v1, double v2, double v3, optional double alpha);
};

이는 아래처럼 두 개의 오버로딩된 연산을 가진 인터페이스와 같습니다:

[Exposed=Window]
interface ColorCreator {
  object createColor(double v1, double v2, double v3);
  object createColor(double v1, double v2, double v3, double alpha);
};

아래 IDL 프래그먼트는 딕셔너리 인자를 받는 연산을 가진 인터페이스를 정의합니다:

dictionary LookupOptions {
  boolean caseSensitive = false;
};

[Exposed=Window]
interface AddressBook {
  boolean hasAddressForName(USVString name, optional LookupOptions options = {});
};

hasAddressForName을 인자 하나만 넘겨 호출하면, 두 번째 인자는 기본 초기화된 LookupOptions 딕셔너리가 되며, caseSensitive는 false로 설정됩니다.

연산에 적용 가능한 확장 속성은 다음과 같습니다: [CrossOriginIsolated], [Default], [Exposed], [LegacyUnforgeable], [NewObject], [SecureContext].

연산 operation의 메서드 단계는 “operation(arg1, arg2, ...) 메서드 단계는 다음과 같다:”(목록) 또는 “operation(arg1, arg2, ...) 메서드 단계는 다음을 수행한다”(인라인 설명)와 같은 텍스트로 소개해야 합니다.

참고: 메서드 단계를 정의할 때는 this에 암묵적으로 접근할 수 있습니다.

DefaultValue ::
    ConstValue
    string
    [ ]
    { }
    null
    undefined
Operation ::
    RegularOperation
    SpecialOperation
RegularOperation ::
    Type OperationRest
SpecialOperation ::
    Special RegularOperation
Special ::
    getter
    setter
    deleter
OperationRest ::
    OptionalOperationName ( ArgumentList ) ;
OptionalOperationName ::
    OperationName
    ε
OperationName ::
    OperationNameKeyword
    identifier
OperationNameKeyword ::
    includes
ArgumentList ::
    Argument Arguments
    ε
Arguments ::
    , Argument Arguments
    ε
Argument ::
    ExtendedAttributeList ArgumentRest
ArgumentRest ::
    optional TypeWithExtendedAttributes ArgumentName Default
    Type Ellipsis ArgumentName
ArgumentName ::
    ArgumentNameKeyword
    identifier
Ellipsis ::
    ...
    ε
ArgumentNameKeyword ::
    attribute
    callback
    const
    constructor
    deleter
    dictionary
    enum
    getter
    includes
    inherit
    interface
    iterable
    maplike
    mixin
    namespace
    partial
    readonly
    required
    setlike
    setter
    static
    stringifier
    typedef
    unrestricted
2.5.3.1. toJSON

toJSON 일반 연산을 선언함으로써, 인터페이스는 해당 인터페이스를 구현하는 객체를 JSON 타입으로 변환하는 방법을 명세합니다.

toJSON 일반 연산은 이러한 용도를 위해 예약되어 있습니다. 반드시 인자를 받지 않아야 하며, JSON 타입을 반환해야 합니다.

JSON 타입은 다음과 같습니다:

toJSON 일반 연산 이 객체에서 어떻게 노출되는지, 그리고 JSON 타입이 JSON 문자열로 변환되는 방식은 언어 바인딩에 따라 다릅니다.

참고: 자바스크립트 바인딩에서는, toJSON 메서드를 노출하여 JSON 타입을 자바스크립트 값으로 반환하고, JSON.stringify() 함수로 JSON 문자열로 변환할 수 있도록 합니다. 또한, 자바스크립트 바인딩에서 toJSON 연산에 [Default] 확장 속성을 사용할 수 있으며, 이 경우 기본 toJSON 단계가 대신 노출됩니다.

아래 IDL 프래그먼트는 Transaction 인터페이스에 toJSON 메서드를 프로즈로 정의한 예시입니다:

[Exposed=Window]
interface Transaction {
  readonly attribute DOMString from;
  readonly attribute DOMString to;
  readonly attribute double amount;
  readonly attribute DOMString description;
  readonly attribute unsigned long number;
  TransactionJSON toJSON();
};

dictionary TransactionJSON {
  Account from;
  Account to;
  double amount;
  DOMString description;
};

Transaction 인터페이스의 toJSON 일반 연산은 다음과 같이 정의할 수 있습니다:

toJSON() 메서드 단계는 다음과 같다:

  1. json을 새 맵으로둡니다.

  2. 각 속성 identifier attr에 대해 «"from", "to", "amount", "description"»:

    1. value를 getter 단계를 this에 대해 실행한 결과로 둡니다.

    2. json[attr]에 value를 설정합니다.

  3. json을 반환합니다.

자바스크립트 바인딩에서는 Transaction 객체에 toJSON() 메서드가 존재합니다:

// Transaction 인스턴스 얻기
var txn = getTransaction();

// 아래와 같은 객체로 평가됨:
// {
//   from: "Bob",
//   to: "Alice",
//   amount: 50,
//   description: "books"
// }
txn.toJSON();

// 아래와 같은 문자열로 평가됨:
// '{"from":"Bob","to":"Alice","amount":50,"description":"books"}'
JSON.stringify(txn);

2.5.4. 생성자 연산

인터페이스에 생성자 연산 멤버(Constructor에 일치)가 있으면, 해당 인터페이스를 구현하는 객체를 생성자를 통해 만들 수 있다는 뜻입니다.

하나의 인터페이스에는 여러 개의 생성자 연산이 있을 수 있습니다. 인터페이스의 각각의 생성자 연산에 대해, 지정된 인자를 넘겨 인스턴스를 생성할 방법이 제공됩니다.

생성자 연산이 인터페이스 interface의 멤버일 때 생성자 단계는 “The new interface(arg1, arg2, ...) 생성자 단계는 다음과 같다:”(목록) 또는 “The new interface(arg1, arg2, ...) 생성자 단계는 다음을 수행한다”(인라인 설명)와 같은 텍스트로 소개해야 합니다.

생성자 단계는 아무 것도 하지 않거나, this에 전달된 값을 초기화하거나, 예외를 던질 수 있습니다.

생성자가 this를 초기화하지 않는 경우, “The new Example(init) 생성자 단계는 아무 것도 하지 않는다.”라고 쓸 수 있습니다.

§ 3.7.1 인터페이스 객체에서 생성자 연산이 어떻게 구현되는지 자세히 설명합니다.

아래 IDL은 두 개의 인터페이스를 정의합니다. 두 번째 인터페이스에는 생성자 연산이 있지만, 첫 번째에는 없습니다.

[Exposed=Window]
interface NodeList {
  Node item(unsigned long index);
  readonly attribute unsigned long length;
};

[Exposed=Window]
interface Circle {
  constructor();
  constructor(double radius);
  attribute double r;
  attribute double cx;
  attribute double cy;
  readonly attribute double circumference;
};

이 인터페이스들을 지원하는 자바스크립트 구현에서는 Circle 인터페이스 객체에 [[Construct]] 내부 메서드를 구현하며, 이를 통해 해당 인터페이스를 구현하는 새 객체를 반환합니다. 인자는 0개 또는 1개를 받을 수 있습니다.

NodeList 인터페이스 객체가 [[Construct]] 내부 메서드를 구현하는지는 명확하지 않습니다. 어쨌든 이를 생성자로 사용하려 하면 TypeError가 발생합니다. [whatwg/webidl Issue #698]

var x = new Circle();      // 0개 인자 생성자로 Circle 인터페이스 구현 객체 생성
                           // 플랫폼 객체 참조 반환

var y = new Circle(1.25);  // 1개 인자 생성자로 Circle 객체 생성

var z = new NodeList();    // 생성자 선언이 없으므로 TypeError 발생
Constructor ::
    constructor ( ArgumentList ) ;
ArgumentList ::
    Argument Arguments
    ε
Arguments ::
    , Argument Arguments
    ε
Argument ::
    ExtendedAttributeList ArgumentRest
ArgumentRest ::
    optional TypeWithExtendedAttributes ArgumentName Default
    Type Ellipsis ArgumentName
ArgumentName ::
    ArgumentNameKeyword
    identifier
Ellipsis ::
    ...
    ε
ArgumentNameKeyword ::
    attribute
    callback
    const
    constructor
    deleter
    dictionary
    enum
    getter
    includes
    inherit
    interface
    iterable
    maplike
    mixin
    namespace
    partial
    readonly
    required
    setlike
    setter
    static
    stringifier
    typedef
    unrestricted

2.5.5. 문자열 변환자

인터페이스에 문자열 변환자가 있으면, 해당 인터페이스를 구현하는 객체가 기본값이 아닌 문자열 변환(conversion)을 갖는다는 의미입니다. 문자열 변환자는 stringifier 키워드로 지정할 수 있으며, 단독으로 사용될 경우 문자열 변환 연산을 만듭니다.

interface interface_identifier {
  stringifier;
};

인터페이스와 함께 설명되는 프로즈(prose)에서는 해당 인터페이스의 문자열 변환 동작을 정의해야 합니다.

stringifier 키워드는 속성에도 사용할 수 있습니다. 이 경우, 객체를 문자열로 변환할 때 사용할 값은 해당 속성의 값입니다. stringifier 키워드는 반드시 DOMString 또는 USVString 타입의 속성에만 사용할 수 있습니다. 또한 정적 속성에는 사용할 수 없습니다.

interface interface_identifier {
  stringifier attribute DOMString identifier;
};

특정 인터페이스에는 문자열 변환자가 최대 하나만 존재해야 합니다.

Stringifier ::
    stringifier StringifierRest
StringifierRest ::
    OptionalReadOnly AttributeRest
    ;

아래 IDL 프래그먼트는 name 속성 값으로 문자열 변환되는 인터페이스를 정의합니다:

[Exposed=Window]
interface Student {
  constructor();
  attribute unsigned long id;
  stringifier attribute DOMString name;
};

자바스크립트 바인딩에서 Student 객체를 문자열이 필요한 곳에서 사용하면 객체의 name 속성 값이 사용됩니다:

var s = new Student();
s.id = 12345678;
s.name = '周杰倫';

var greeting = 'Hello, ' + s + '!';  // greeting == 'Hello, 周杰倫!'

아래 IDL 프래그먼트는 IDL 자체에 명시되지 않은 커스텀 문자열 변환 동작을 가진 인터페이스를 정의합니다.

[Exposed=Window]
interface Student {
  constructor();
  attribute unsigned long id;
  attribute DOMString? familyName;
  attribute DOMString givenName;

  stringifier;
};

따라서 문자열 변환 동작을 설명하는 프로즈가 필요합니다. familyName과 givenName 속성은 각각 성과 이름 개념을 나타낸다고 가정합니다.

문자열 변환 동작 단계는 다음과 같다:

  1. this의 family name이 null이면, this의 given name을 반환한다.

  2. this의 given name, U+0020 SPACE, this의 family name을 순서대로 이어붙여 반환한다.

이 IDL의 자바스크립트 구현 동작 예시는 다음과 같습니다:

var s = new Student();
s.id = 12345679;
s.familyName = 'Smithee';
s.givenName = 'Alan';

var greeting = 'Hi ' + s;  // greeting == 'Hi Alan Smithee'

2.5.6. 특수 연산

특수 연산은 해당 인터페이스를 구현하는 객체에 특정 종류의 특별한 동작을 선언하는 것입니다. 특수 연산은 연산 선언에 특수 키워드를 사용해 선언합니다.

특수 연산에는 세 가지 종류가 있습니다. 아래 표는 각 특수 연산의 종류별로 사용되는 특수 키워드와 그 목적을 나타냅니다:

특수 연산 키워드 목적
Getter getter 객체가 프로퍼티 조회를 위해 인덱싱될 때 동작을 정의합니다.
Setter setter 객체가 프로퍼티 할당 또는 생성 시 인덱싱될 때 동작을 정의합니다.
Deleter deleter 객체가 프로퍼티 삭제를 위해 인덱싱될 때 동작을 정의합니다.

모든 언어 바인딩이 네 가지 종류의 특수 객체 동작을 모두 지원하는 것은 아닙니다. 특수 연산이 식별자 없이 선언된 경우, 해당 종류의 특수 연산을 지원하지 않는 언어 바인딩에서는 해당 기능이 제공되지 않습니다.

아래 IDL 프래그먼트는 getter와 setter가 있는 인터페이스를 정의합니다:

[Exposed=Window]
interface Dictionary {
  readonly attribute unsigned long propertyCount;

  getter double (DOMString propertyName);
  setter undefined (DOMString propertyName, double propertyValue);
};

프로퍼티 getter와 setter를 지원하지 않는 언어 바인딩에서는, Dictionary를 구현하는 객체가 해당 특별 동작을 갖지 않습니다.

특수 연산을 식별자를 사용해 정의하는 것은, 해당 특수 연산을 식별자 없이 별도의 선언으로 분리하는 것과 동등합니다. 이 방식은 인터페이스 연산의 메서드 단계를 단순화하기 위해 허용됩니다.

다음 두 인터페이스는 동등합니다:

[Exposed=Window]
interface Dictionary {
  readonly attribute unsigned long propertyCount;

  getter double getProperty(DOMString propertyName);
  setter undefined setProperty(DOMString propertyName, double propertyValue);
};
[Exposed=Window]
interface Dictionary {
  readonly attribute unsigned long propertyCount;

  double getProperty(DOMString propertyName);
  undefined setProperty(DOMString propertyName, double propertyValue);

  getter double (DOMString propertyName);
  setter undefined (DOMString propertyName, double propertyValue);
};

특정 특수 키워드는 연산에서 두 번 이상 등장해서는 안 됩니다.

Getter와 setter에는 두 가지 종류가 있습니다: DOMString을 프로퍼티 이름으로 받는 이름 있는 프로퍼티 getter와 이름 있는 프로퍼티 setter가 있고, unsigned long을 프로퍼티 인덱스로 받는 인덱스 프로퍼티 getter 및 인덱스 프로퍼티 setter가 있습니다. deleter는 한 종류만 있습니다: 이름 있는 프로퍼티 deleter. 자세한 내용은 § 2.5.6.1 인덱스 프로퍼티와 § 2.5.6.2 이름 프로퍼티를 참조하세요.

특정 인터페이스에는 이름 있는 프로퍼티 deleter가 최대 하나, getter와 setter의 각 종류도 최대 하나만 존재해야 합니다.

인터페이스에 특정 종류의 setter가 있으면 반드시 같은 종류의 getter도 있어야 합니다. 이름 있는 프로퍼티 deleter가 있으면, 반드시 이름 있는 프로퍼티 getter도 있어야 합니다.

연산으로 선언된 특수 연산은 가변 인자(variadic)가 아니어야 하며, 옵션 인자를 가질 수 없습니다.

객체가 두 개 이상의 인터페이스를 구현하며, 동일한 특수 연산을 정의한다면, 실제 어떤 특수 연산이 호출되는지는 정의되지 않습니다.

2.5.6.1. 인덱스 프로퍼티

인덱스 프로퍼티 getter를 정의한 인터페이스는 인덱스 프로퍼티를 지원한다고 한다. 확장해서, 플랫폼 객체가 인덱스 프로퍼티를 지원한다고 하려면 해당 객체가 인덱스 프로퍼티를 지원하는 인터페이스를 구현하면 된다.

인터페이스가 인덱스 프로퍼티를 지원하면, 인터페이스 정의에는 객체가 언제든지 어떤 인덱스로 인덱싱될 수 있는지 기술이 포함되어야 한다. 이 인덱스들을 지원되는 프로퍼티 인덱스라고 한다.

인덱스 프로퍼티를 지원하는 인터페이스는 "length"라는 정수형 속성을 정의해야 한다.

인덱스 프로퍼티 getter는 반드시 unsigned long 하나의 인자를 받아야 한다. 인덱스 프로퍼티 setter는 반드시 두 개의 인자를 받아야 하며, 첫 번째 인자는 unsigned long이어야 한다.

interface interface_identifier {
  getter type identifier(unsigned long identifier);
  setter type identifier(unsigned long identifier, type identifier);

  getter type (unsigned long identifier);
  setter type (unsigned long identifier, type identifier);
};

인덱스 프로퍼티 getter와 setter 정의에는 다음 요구 사항이 적용된다:

인덱스 프로퍼티 getter나 setter가 연산에 식별자를 써서 지정된 경우, 객체를 정수로 인덱싱할 때(지원되는 프로퍼티 인덱스가 아닌 경우) 해당 연산을 해당 인덱스로 호출하는 것과 같은 동작을 반드시 하지는 않는다. 실제 동작은 언어 바인딩마다 다르다.

자바스크립트 바인딩에서는 일반 프로퍼티 조회가 실행된다. 예를 들어, 아래 IDL을 보자:

[Exposed=Window]
interface A {
  getter DOMString toWord(unsigned long index);
};

A를 구현하는 객체가 지원되는 프로퍼티 인덱스를 0 ≤ index < 2로 가진다고 가정하고, toWord는 인자를 영어 단어로 바꿔 반환한다고 하자. 인덱스가 범위를 벗어난 경우 연산 호출과 직접 인덱싱은 다르게 동작한다:

var a = getA();

a.toWord(0);  // "zero" 반환
a[0];         // 역시 "zero" 반환

a.toWord(5);  // "five" 반환
a[5];         // "5"라는 프로퍼티가 없으므로 undefined 반환

아래 IDL 프래그먼트는 OrderedMap 인터페이스를 정의하며, 이름 또는 인덱스 번호로 값을 조회/설정할 수 있습니다:

[Exposed=Window]
interface OrderedMap {
  readonly attribute unsigned long size;

  getter any getByIndex(unsigned long index);
  setter undefined setByIndex(unsigned long index, any value);

  getter any get(DOMString name);
  setter undefined set(DOMString name, any value);
};

모든 특수 연산이 식별자를 사용한 연산으로 선언되어 있으므로, 추가적으로 필요한 프로즈는 어떤 키들이 있는지에 대한 설명뿐입니다. get() 연산이 존재하지 않는 항목을 조회할 때 null을 반환하도록 정의된 경우, 아래 두 문장으로 충분합니다:

OrderedMap을 구현하는 객체 map은 0 ≤ index < map.size 범위의 인덱스 프로퍼티를 지원한다.

또한, get()에 넘겼을 때 null이 아닌 값을 반환하는 모든 이름에 대해 이름 프로퍼티도 지원한다.

§ 3.9 레거시 플랫폼 객체에서 설명한 대로, 자바스크립트 구현에서는 레거시 플랫폼 객체에 OrderedMap 인터페이스의 이름/인덱스 프로퍼티에 해당하는 프로퍼티가 생성된다. 이 프로퍼티들은 객체의 메서드를 호출하는 것과 동일하게 상호작용할 수 있으며, 아래 예시처럼 사용할 수 있습니다:

// map은 OrderedMap 인터페이스를 구현하는 레거시 플랫폼 객체라고 가정
var map = getOrderedMap();
var x, y;

x = map[0];       // map.length > 0이면 아래와 동등:
                  // x = map.getByIndex(0)
                  // 즉, map에 "0"이라는 프로퍼티가 있으므로
                  // 그렇지 않으면 x는 undefined

map[1] = false;   // 아래와 동등:
                  // map.setByIndex(1, false)

y = map.apple;    // apple이라는 이름 프로퍼티가 있으면 아래와 동등:
                  // y = map.get('apple')
                  // 없으면 y는 undefined

map.berry = 123;  // 아래와 동등:
                  // map.set('berry', 123)

delete map.cake;  // cake라는 이름 프로퍼티가 있으면 해당 프로퍼티 삭제 후 아래 동등:
                  // map.remove("cake")
2.5.6.2. 이름 프로퍼티

이름 프로퍼티 getter를 정의한 인터페이스는 이름 프로퍼티를 지원한다고 한다. 확장해서, 플랫폼 객체가 이름 프로퍼티를 지원한다고 하려면 해당 객체가 이름 프로퍼티를 지원하는 인터페이스를 구현하면 된다.

인터페이스가 이름 프로퍼티를 지원하면, 인터페이스 정의에는 객체를 언제든지 어떤 이름으로 인덱싱할 수 있는지(순서가 있는 이름 집합) 기술이 포함되어야 한다. 이 이름들을 지원되는 프로퍼티 이름이라고 한다.

이름 프로퍼티 getter와 deleter는 반드시 DOMString 하나의 인자를 받아야 한다. 이름 프로퍼티 setter는 반드시 두 개의 인자를 받아야 하며, 첫 번째 인자는 DOMString이어야 한다.

interface interface_identifier {
  getter type identifier(DOMString identifier);
  setter type identifier(DOMString identifier, type identifier);
  deleter type identifier(DOMString identifier);

  getter type (DOMString identifier);
  setter type (DOMString identifier, type identifier);
  deleter type (DOMString identifier);
};

이름 프로퍼티 getter, setter, deleter 정의에는 다음 요구 사항이 적용된다:

참고: 인덱스 프로퍼티와 마찬가지로, 이름 프로퍼티 getter, setter 또는 deleter 가 연산에 식별자를 써서 지정된 경우, 객체를 지원되는 프로퍼티 이름이 아닌 이름으로 인덱싱할 때 해당 연산을 해당 이름으로 호출하는 것과 반드시 같은 동작을 하는 것은 아니며, 실제 동작은 언어 바인딩마다 다릅니다.

2.5.7. 정적 속성 및 연산

정적 속성 및 정적 연산 은 해당 인터페이스의 특정 인스턴스가 아니라 인터페이스 자체에 연결되는 속성/연산입니다. 정적 속성과 연산은 선언에 static 키워드를 사용해 지정합니다.

정적 연산을 호출하거나 정적 속성을 참조하는 것이 인터페이스 인스턴스에서 가능한지는 언어 바인딩마다 다릅니다.

StaticMember ::
    static StaticMemberRest
StaticMemberRest ::
    OptionalReadOnly AttributeRest
    RegularOperation

아래 IDL 프래그먼트는 Circle 인터페이스에 정적 연산이 선언된 예시입니다:

[Exposed=Window]
interface Point { /* ... */ };

[Exposed=Window]
interface Circle {
  attribute double cx;
  attribute double cy;
  attribute double radius;

  static readonly attribute long triangulationCount;
  static Point triangulate(Circle c1, Circle c2, Circle c3);
};

자바스크립트 바인딩에서는 triangulate의 함수 객체와 triangulationCount의 접근자 프로퍼티가 Circle의 인터페이스 객체에 존재합니다:

var circles = getCircles();           // Circle 객체 배열

typeof Circle.triangulate;            // "function" 반환
typeof Circle.triangulationCount;     // "number" 반환
Circle.prototype.triangulate;         // undefined 반환
Circle.prototype.triangulationCount;  // 역시 undefined 반환
circles[0].triangulate;               // 이 역시 undefined
circles[0].triangulationCount;        // 이것도 undefined

// 정적 연산 호출
var triangulationPoint = Circle.triangulate(circles[0], circles[1], circles[2]);

// 수행한 삼각분할 개수 확인
window.alert(Circle.triangulationCount);

2.5.8. 오버로딩

인터페이스에 정의된 일반 연산 또는 정적 연산이 동일한 종류(일반 또는 정적)의 다른 연산과 동일한 식별자를 가지면, 해당 연산은 오버로딩된 연산이라 한다. 오버로딩된 연산의 식별자가 인터페이스를 구현하는 객체에서 호출될 때, 전달된 인자의 개수와 타입에 따라 실제로 어떤 오버로딩된 연산이 호출되는지가 결정된다. 생성자 연산도 오버로딩될 수 있다. 오버로딩된 연산과 생성자가 받을 수 있는 인자에는 몇 가지 제한이 있으며, 이를 설명하기 위해 유효 오버로드 집합이라는 개념을 사용한다.

오버로딩된 연산 집합은 다음 중 하나를 만족해야 한다:

연산은 인터페이스, 부분 인터페이스, 인터페이스 믹스인, 부분 인터페이스 믹스인 정의를 넘나들어 오버로딩될 수 없다.

예를 들어, 아래의 f와 g에 대한 오버로딩은 허용되지 않는다:

[Exposed=Window]
interface A {
  undefined f();
};

partial interface A {
  undefined f(double x);
  undefined g();
};

partial interface A {
  undefined g(DOMString x);
};

참고로 생성자 연산과 [LegacyFactoryFunction] 확장 속성은 부분 인터페이스 정의에는 등장할 수 없으므로, 생성자 오버로딩을 추가로 금지할 필요는 없다.

유효 오버로드 집합은 특정 연산, 생성자(생성자 연산 또는 [LegacyFactoryFunction]), 또는 콜백 함수에 대해 허용되는 호출을 나타낸다. 유효 오버로드 집합 계산 알고리즘은 다음 네 가지 IDL 구조에 대해 동작하며, 각 구조마다 필요한 입력이 있다:

일반 연산의 경우
정적 연산의 경우
생성자의 경우
레거시 팩토리 함수의 경우

유효 오버로드 집합은 인터페이스에 지정된 오버로딩 연산과 생성자에 모호함이 있는지 판별하는 데 사용된다.

아이템들은 유효 오버로드 집합의 튜플로, (호출 객체, 타입 리스트, 옵셔널리티 리스트) 형태를 가진다. 아래에 각 아이템 설명:

각 튜플은 해당 타입의 인자값 리스트로 연산, 생성자, 콜백 함수를 호출할 수 있음을 의미한다. 옵션 인자 및 가변 인자 연산/생성자 덕분에, 동일한 연산이나 생성자로 식별되는 유효 오버로드 집합 아이템이 여러 개 있을 수 있다.

아래 알고리즘은 유효 오버로드 집합 계산 방법을 설명한다. 다음 입력 변수들을 사용한다(필요한 경우):

확장 속성의 인자란, 확장 속성의 명명된 인자 리스트의 인자를 의미한다.

  1. S를 순서 있는 집합으로 둔다.

  2. F를 순서 있는 집합으로 둔다. 아이템은 유효 오버로드 집합 종류에 따라 다음과 같다:

    일반 연산의 경우

    F의 요소는 인터페이스 I에 정의된 A 식별자의 일반 연산이다.

    정적 연산의 경우

    F의 요소는 인터페이스 I에 정의된 A 식별자의 정적 연산이다.

    생성자의 경우

    F의 요소는 인터페이스 I의 생성자 연산이다.

    레거시 팩토리 함수의 경우

    F의 요소는 인터페이스 I에 정의된 [LegacyFactoryFunction] 확장 속성 중 명명된 인자 리스트의 식별자가 A인 것들이다.

  3. maxarg를 F의 연산, 레거시 팩토리 함수, 콜백 함수에서 선언된 최대 인자 개수로 둔다. 가변 인자 연산 및 레거시 팩토리 함수에서, ...이 붙은 인자는 1개로 센다.

    참고: undefined f(long x, long... y);는 인자 2개로 간주된다.

  4. max를 max(maxarg, N)로 둔다.

  5. 각 F의 연산 또는 확장 속성 X에 대해:

    1. arguments를 X에 선언된 인자들의 리스트로 둔다.

    2. n을 arguments의 크기로 둔다.

    3. types를 타입 리스트로 둔다.

    4. optionalityValues를 옵셔널리티 리스트로 둔다.

    5. 각 arguments의 argument에 대해:

      1. types에 argument의 타입을 추가한다.

      2. optionalityValues에, argument가 마지막 가변 인자면 "variadic", 옵션 인자면 "optional", 그 외는 "required"를 추가한다.

    6. S에 (X, types, optionalityValues) 튜플을 추가한다.

    7. X가 가변 인자로 선언되었다면:

      1. 각 i에 대해, 범위 n부터 max까지(끝값 제외):

        1. t를 타입 리스트로 둔다.

        2. o를 옵셔널리티 리스트로 둔다.

        3. 각 j에 대해, 범위 0부터 n까지, 끝값 제외:

          1. t에 types[j]를 추가한다.

          2. o에 optionalityValues[j]를 추가한다.

        4. 각 j에 대해, 범위 n부터 i까지, 끝값 포함:

          1. t에 types[n−1]를 추가한다.

          2. o에 "variadic"을 추가한다.

        5. S에 (X, t, o) 튜플을 추가한다.

    8. i를 n−1로 둔다.

    9. i ≥ 0인 동안:

      1. arguments[i]가 옵션 인자가 아니면 break.

      2. t를 타입 리스트로 둔다.

      3. o를 옵셔널리티 리스트로 둔다.

      4. 각 j에 대해, 범위 0부터 i까지, 끝값 제외:

        1. t에 types[j]를 추가한다.

        2. o에 optionalityValues[j]를 추가한다.

      5. S에 (X, t, o) 튜플을 추가한다.

        참고: i가 0이면 S에 (X, « », « ») (여기서 "« »"는 빈 리스트)를 추가한다는 뜻이다.

      6. i를 i−1로 둔다.

  6. S를 반환한다.

다음 인터페이스에 대해:

[Exposed=Window]
interface A {
  /* f1 */ undefined f(DOMString a);
  /* f2 */ undefined f(Node a, DOMString b, double... c);
  /* f3 */ undefined f();
  /* f4 */ undefined f(Event a, DOMString b, optional DOMString c, double... d);
};

Node와 Event가 서로 다른 인터페이스이며, 어떤 객체도 둘 다를 구현할 수 없다면, 일반 연산의 식별자 f와 인자 개수 4에 대해 유효 오버로드 집합은 다음과 같다:

«
  (f1, « DOMString »,                           « required »),
  (f2, « Node, DOMString »,                     « required, required »),
  (f2, « Node, DOMString, double »,             « required, required, variadic »),
  (f2, « Node, DOMString, double, double »,     « required, required, variadic, variadic »),
  (f3, « »,                                     « »),
  (f4, « Event, DOMString »,                    « required, required »),
  (f4, « Event, DOMString, DOMString »,         « required, required, optional »),
  (f4, « Event, DOMString, DOMString, double », « required, required, optional, variadic »)
»

두 타입이 구별 가능하다는 것은 다음 알고리즘이 true를 반환하는 경우이다.

  1. 한 타입이 널 허용 타입을 포함하고, 다른 타입이 널 허용 타입을 포함하거나, 유니온 타입이며 평탄화된 멤버 타입에 딕셔너리 타입이 포함되거나, 딕셔너리 타입이면, false를 반환한다.

    아래 쌍들은 구별 불가능하다:
  2. 두 타입 모두 유니온 타입 또는 널 허용 유니온 타입이면, 각 멤버 타입이 서로 구별 가능하면 true, 아니면 false를 반환한다.

  3. 한 타입이 유니온 타입 또는 널 허용 유니온 타입이면, 유니온 타입의 각 멤버 타입이 비유니온 타입과 구별 가능하면 true, 아니면 false를 반환한다.

  4. 각 타입의 내부 타입(주석 타입이면)과 내부 타입(그 결과가 널 허용 타입이면)을 취한 "가장 안쪽" 타입을 고려한다. 이 두 타입이 아래 표의 카테고리에 속하고, 해당 교차점에 ● 또는 지정된 조건(a, b, c, d)이 만족되면 true, 아니면 false를 반환한다.

    카테고리:

    interface-like
    dictionary-like
    sequence-like
    undefined
    boolean
    numeric types
    bigint
    string types
    object
    symbol
    interface-like
    callback function
    dictionary-like
    async sequence
    sequence-like
    undefined ● ● ● ● ● ● ● ● ● ●
    boolean ● ● ● ● ● ● ● ● ● ●
    numeric types (b) ● ● ● ● ● ● ● ●
    bigint ● ● ● ● ● ● ● ●
    string types ● ● ● ● ● (d) ●
    object ●
    symbol ● ● ● ● ●
    interface-like (a) ● ● ● ●
    callback function (c) ● ●
    dictionary-like ● ● ●
    async sequence
    sequence-like
    1. 식별된 두 interface-like 타입이 서로 다르고, 어떤 플랫폼 객체도 두 타입을 모두 구현하지 않는다.

    2. 타입이 구별 가능하지만, 오버로딩에서 사용에 별도의 제한이 있다. 또한 이 타입의 유니온 사용에 관한 조언도 참고할 것.

    3. [LegacyTreatNonObjectAsNull] 확장 속성이 없는 콜백 함수는 dictionary-like 카테고리 타입과 구별 가능하다.

      예를 들어, ECMAScript 값을 콜백 함수와 딕셔너리-like 타입을 포함하는 유니온 타입으로 변환할 때, 값이 호출 가능이면 콜백 함수로, 아니면 딕셔너리-like 타입으로 변환된다.
    4. 타입은 구별 가능하지만, 문자열 타입 이 오버로드 집합이나 유니온에도 있으면 ECMAScript 값에서 변환할 때 문자열 객체 는 비동기 시퀀스 타입 으로 변환되지 않는다( %Symbol.iterator% 메서드가 있더라도).

    double 과 DOMString 은 숫자 타입과 문자열 타입 교차점에 ●이 있으므로 구별 가능하다.
    double 과 long은 모두 숫자 타입이므로, 숫자 타입과 숫자 타입의 교차점에 ●이나 문자가 없으므로 구별 불가능하다.
    다음과 같을 때:
    callback interface CBIface {
        undefined handle();
    };
    
    [Exposed=Window]
    interface Iface {
        attribute DOMString attr2;
    };
    
    dictionary Dict {
        DOMString field1;
    };
    

    CBIface는 Iface와는 구별 가능하다(딕셔너리-like와 인터페이스-like 교차점에 ●이 있음). 하지만 Dict와는 구별 불가능하다(딕셔너리-like 교차점에 ● 없음).

    프라미스 타입은 위 표에 없으므로, 어떤 다른 타입과도 구별 불가능하다.

주어진 효과적 오버로드 집합 에서 같은 타입 리스트 크기 를 갖는 항목 이 둘 이상이면, 그러한 항목들에 대해 어떤 인덱스 i 가 존재하여 모든 항목 쌍의 인덱스 i 에 있는 타입들이 구별 가능 해야 합니다. 이 조건을 만족하는 가장 작은 인덱스를, 해당 타입 리스트 크기를 갖는 효과적 오버로드 집합 의 항목들에 대한 구별 인자 인덱스 라고 합니다.

효과적 오버로드 집합 에는 같은 타입 리스트 크기 를 갖는 항목 이 둘 이상 있으면서, 그중 하나의 항목 은 구별 인자 인덱스 에 bigint 인자를 갖고 다른 하나는 구별 인자 인덱스 에 숫자 타입 인자를 갖는 경우가 있어서는 안 됩니다.

앞 예시의 유효 오버로드 집합을 생각해보자. type list가 2, 3, 4인 아이템이 여러 개 있다. 각 type list 크기별로 구별 인자 인덱스는 0이다. Node와 Event가 구별 가능이기 때문이다.

아래와 같은 오버로딩은 허용되지 않는다:

[Exposed=Window]
interface B {
  undefined f(DOMString x);
  undefined f(USVString x);
};

DOMString 과 USVString 은 구별 불가능하기 때문이다.

또한, 어떤 type list 크기의 구별 인자 인덱스보다 작은 인덱스 j에 대해, 모든 아이템의 type list에서 j번째 타입이 같아야 하며, 모든 아이템의 optionality list에서 j번째 optionality 값도 같아야 한다.

다음은 허용되지 않는다:

[Exposed=Window]
interface B {
  /* f1 */ undefined f(DOMString w);
  /* f2 */ undefined f(long w, double x, Node y, Node z);
  /* f3 */ undefined f(double w, double x, DOMString y, Node z);
};

인자 개수 4에서의 유효 오버로드 집합은 아래와 같다:

«
  (f1, « DOMString »,                       « required »),
  (f2, « long, double, Node, Node »,        « required, required, required, required »),
  (f3, « double, double, DOMString, Node », « required, required, required, required »)
»

type list 크기가 4인 아이템들에서, 구별 인자 인덱스 는 2이다. Node와 DOMString 이 구별 가능이기 때문이다. 그러나 이 두 오버로드의 0번째 인자 타입이 다르므로, 오버로딩은 허용되지 않는다.

2.5.8.1. 오버로딩 vs. 유니온 타입

이 섹션은 참고용입니다.

IDL 연산을 정의하는 명세에서, 오버로딩과 유니온 타입, 옵션 인자 조합이 기능적으로 겹치는 부분이 있어 보일 수 있습니다.

먼저 오버로딩은 유니온 타입이나 옵션 인자와는 동작이 다르며, 하나로 완전히 대체할 수 없다(물론 추가적인 프로즈가 있으면 가능하지만, 이는 Web IDL 타입 시스템의 목적에 어긋난다). 예를 들어 stroke() 연산이 CanvasDrawPath 인터페이스에 정의되어 있다고 하자 [HTML]:

interface CanvasDrawPathExcerpt {
  undefined stroke();
  undefined stroke(Path2D path);
};

자바스크립트 바인딩에서는, stroke(undefined)를 호출하면 두 번째 오버로드가 선택되며, TypeError 가 발생한다. undefined가 Path2D로 변환될 수 없기 때문이다. 하지만 연산이 옵션 인자로 하나로 합쳐진다면,

interface CanvasDrawPathExcerptOptional {
  undefined stroke(optional Path2D path);
};

오버로드 결정 알고리즘은 path 인자를 누락된 것으로 처리하고 예외를 발생시키지 않습니다.

참고: 이 예시에서 후자의 동작이 실제로 Web 개발자가 기대하는 것입니다. CanvasDrawPath 를 새로 설계한다면 옵션 인자로 stroke()를 정의할 것입니다.

또한 의미적 차이도 있습니다. 유니온 타입은 "어떤 타입이든 동작이 대체로 같다"는 의미로 주로 쓰이고, 오버로딩된 연산은 C++ 등 언어의 오버로딩과 잘 대응되는 구조로, 인자 타입에 따라 동작이 크게 달라지는 경우에 더 적합합니다. 하지만 이런 경우 대부분은 혼동을 피하기 위해 연산 이름을 다르게 하는 것이 좋으며, 자바스크립트는 언어 차원의 오버로딩을 제공하지 않으므로 새로운 API에는 오버로딩은 거의 적합하지 않고, 레거시 API나 특수한 경우에만 사용됩니다.

그래도 어떤 IDL 기능을 사용할지 어려울 때 아래와 같은 권고와 예시를 참고하세요:

위 경우에 해당하지 않으면 명세 작성자가 스타일을 선택하면 됩니다. 둘 중 어느 쪽도 의도한 동작을 충분히 표현할 수 있기 때문입니다. 단, 변환 알고리즘 및 유니온 타입, 옵션 인자의 정의가 오버로딩 결정 알고리즘보다 구현과 이해가 쉽고, 자바스크립트 바인딩에 더 적합한 API를 만드는 경우가 많다. 특별한 이유가 없다면 유니온 타입, 옵션 인자를 기본 선택으로 삼길 권장한다.

명세는 필요하다면 유니온 타입과 오버로딩을 혼합해 사용할 수도 있다.

2.5.9. 이터러블 선언

인터페이스는 이터러블로 선언될 수 있으며, 이는 인터페이스 본문에 이터러블 선언(Iterable에 일치)을 사용하여 지정한다.

interface interface_identifier {
  iterable<value_type>;
  iterable<key_type, value_type>;
};

인터페이스를 이터러블로 구현한 객체는 값을 시퀀스로 얻을 수 있도록 반복(iterate)할 수 있다.

참고: 자바스크립트 바인딩에서는 이터러블 인터페이스의 인터페이스 프로토타입 객체에 entries, forEach, keys, values, %Symbol.iterator% 프로퍼티가 있다.

타입 파라미터가 하나면 값 이터레이터이며, 해당 타입의 값을 제공한다. 타입 파라미터가 둘이면 쌍 이터레이터이며, 값 쌍을 제공한다.

값 쌍은 키 타입과 값 타입이 주어졌을 때 두 개의 구조체 아이템으로 이루어진다:

  1. 아이템의 이름이 "key"이고, 값 쌍의 키라 하며, 값은 키 타입의 IDL 값이다;

  2. 아이템의 이름이 "value"이고, 값 쌍의 값이라 하며, 값은 값 타입의 IDL 값이다.

값 이터레이터는 반드시 인덱스 프로퍼티를 지원하는 인터페이스에만 선언될 수 있다. 값 이터레이터의 value-type은 인덱스 프로퍼티 getter가 반환하는 타입과 같아야 한다. 값 이터레이터는 해당 객체의 인덱스 프로퍼티를 반복(iterate)하는 것으로 암묵적으로 정의된다.

쌍 이터레이터는 인덱스 프로퍼티를 지원하는 인터페이스에 선언될 수 없다.

페어 반복자가 있는 인터페이스에 대한 설명은 각 인터페이스 인스턴스마다 리스트를 값 쌍의 형태로 정의해야 하며, 이 리스트는 반복할 값 쌍입니다.

자바스크립트에서 값 이터레이터의 forEach 메서드는 Array.prototype.forEach처럼 콜백을 호출하고, 쌍 이터레이터의 forEach는 Map.prototype.forEach처럼 호출한다.

값 이터레이터는 현재 인덱스 프로퍼티를 지원하는 인터페이스에만 허용되므로 Array 스타일 forEach가 적합하다. 인덱스 프로퍼티를 지원하지 않는 인터페이스나, Set.prototype.forEach처럼 key와 value가 같은 forEach가 필요한 값을 반복하는 이터레이터가 필요하다면, 이슈를 등록해 주세요.

참고: 이는 array 이터레이터 객체 동작 방식이다. 인덱스 프로퍼티를 지원하는 인터페이스의 경우, entries, keys, values, %Symbol.iterator% 가 반환하는 이터레이터 객체는 실제 array 이터레이터 객체이다.

이터러블 선언이 있는 인터페이스에는 "entries", "forEach", "keys", "values"라는 이름의 속성, 상수, 일반 연산이 존재해서는 안 되며, 상속받은 인터페이스에도 이 이름의 속성, 상수, 일반 연산이 존재해서는 안 된다.

다음 SessionManager 인터페이스는 username을 키로 Session 객체를 참조할 수 있다:

[Exposed=Window]
interface SessionManager {
  Session getSessionForUser(DOMString username);

  iterable<DOMString, Session>;
};

[Exposed=Window]
interface Session {
  readonly attribute DOMString username;
  // ...
};

이터레이터의 동작은 아래처럼 정의될 수 있다:

반복할 값 쌍은 username을 key, 해당 username에 대응하는 SessionManager 객체의 열린 Session 객체를 value로 하여, username 기준으로 정렬된 값 쌍 리스트이다.

자바스크립트 바인딩에서 SessionManager 인터페이스의 인터페이스 프로토타입 객체에는 values 메서드가 있고, 이 함수는 호출 시 다음 값을 반환하는 next 메서드를 가진 이터레이터 객체를 반환한다. keys와 entries 메서드는 각각 session 객체의 username, username/Session 객체 쌍을 반복한다. %Symbol.iterator% 메서드도 있어서 SessionManager를 for..of 루프에서 사용할 수 있으며, entries와 같은 값을 반복한다:

// SessionManager 인스턴스를 얻는다.
// 예를 들어 "anna", "brian" 유저 세션이 있다고 가정.
var sm = getSessionManager();

typeof SessionManager.prototype.values;            // "function" 반환
var it = sm.values();                              // values()는 이터레이터 객체 반환
String(it);                                        // "[object SessionManager Iterator]" 반환
typeof it.next;                                    // "function" 반환

// 아래 루프는 "anna", "brian"을 로그한다.
for (;;) {
  let result = it.next();
  if (result.done) {
    break;
  }
  let session = result.value;
  console.log(session.username);
}

// 이것도 "anna", "brian"을 로그한다.
for (let username of sm.keys()) {
  console.log(username);
}

// 아래도 동일하다.
for (let [username, session] of sm) {
  console.log(username);
}

인터페이스에는 복수의 이터러블 선언이 없어야 한다. 상속받은 인터페이스에도 이터러블 선언이 있으면 안 된다. 이터러블 선언이 있는 인터페이스와 그 상속 인터페이스에는 maplike 선언, setlike 선언, 비동기 이터러블 선언이 있어서는 안 된다.

이터러블 선언에 적용 가능한 확장 속성: [CrossOriginIsolated], [Exposed], [SecureContext].

Iterable ::
    iterable < TypeWithExtendedAttributes OptionalType > ;
OptionalType ::
    , TypeWithExtendedAttributes
    ε

2.5.10. 비동기 이터러블 선언

인터페이스는 비동기 반복 선언 (AsyncIterable과 일치) 을 인터페이스의 본문에 사용함으로써 비동기적으로 반복 가능하도록 선언할 수 있습니다.

interface interface_identifier {
  async_iterable<value_type>;
  async_iterable<value_type>(/* arguments... */);
  async_iterable<key_type, value_type>;
  async_iterable<key_type, value_type>(/* arguments... */);
};

비동기 이터러블로 선언된 인터페이스를 구현하는 객체는 값을 비동기로 반복(iterate)해서 얻을 수 있다.

타입 파라미터가 하나면 값 비동기 이터러블 선언이며, 해당 타입의 값을 비동기로 제공한다. 두 개면 쌍 비동기 이터러블 선언이며, 값 쌍을 비동기로 제공한다.

인자가 있다면, 비동기 이터러블 선언의 인자(ArgumentList에 일치)는 모두 옵션 인자여야 한다.

자바스크립트 바인딩에서, 비동기 이터러블 인터페이스의 인터페이스 프로토타입 객체에는 %Symbol.asyncIterator% 와 values 프로퍼티가 있다. 쌍 비동기 이터러블 선언이면 entries, keys 프로퍼티도 있다. 이 모든 메서드는 옵션 인자를 받을 수 있으며, 전달된 인자는 비동기 이터러블 선언의 인자 리스트에 대응하며, 비동기 이터레이터 초기화 단계에서 처리된다.

이 요구조건 덕분에 자바스크립트 바인딩에서 for-await-of가 인터페이스 인스턴스에 바로 쓸 수 있다. for-await-of는 %Symbol.asyncIterator%를 인자 없이 호출하기 때문이다.

비동기 이터러블 선언이 있는 인터페이스의 프로즈에는 다음 반복 결과 얻기 알고리즘을 정의해야 한다. 이 알고리즘은 반복 중인 인터페이스 인스턴스와 비동기 이터레이터 객체를 받으며(상태 저장에 유용), Promise를 반환해야 한다. 이 Promise는 reject되거나, 반복 종료 신호를 나타내는 반복 종료 값을 resolve하거나, 아래 중 하나를 resolve한다:

값 비동기 이터러블 선언의 경우:

선언된 타입의 값

쌍 비동기 이터러블 선언의 경우:

선언된 두 타입의 값을 포함하는 튜플

또한 프로즈에서 비동기 이터레이터 반환 알고리즘을 정의할 수 있다. 이 알고리즘은 반복 중인 인터페이스 인스턴스, 비동기 이터레이터 객체, any 타입의 인자 하나를 받는다. 이는 이터레이터가 중단될 때 호출되며, Promise를 반환해야 하며, fulfill되면 값은 무시되고, reject되면 에러가 사용자에게 전달된다.

자바스크립트 바인딩에서는 이 알고리즘을 통해 async iterator의 return()이 호출될 때 동작을 커스터마이즈할 수 있다. 이는 break나 return으로 for-await-of 루프를 빠져나갈 때 가장 흔히 발생한다.

throw()에 대한 유사한 hook도 추가할 수 있다. 현재까지 필요가 없었지만, 그런 API가 필요하다면 이슈를 등록해 주세요.

또한 프로즈에서 비동기 이터레이터 초기화 단계도 정의할 수 있다. 이는 반복 중인 인터페이스 인스턴스, 새로 생성된 이터레이터 객체, 전달된 인자를 나타내는 IDL 값 리스트를 받는다.

비동기 이터러블 선언이 있는 인터페이스에는 "entries", "keys", "values"라는 이름의 속성, 상수, 일반 연산이 존재해서는 안 되며, 상속받은 인터페이스에도 이 이름의 속성, 상수, 일반 연산이 존재해서는 안 된다.

다음 SessionManager 인터페이스는 username을 키로 Session 객체를 참조할 수 있다:

[Exposed=Window]
interface SessionManager {
  Session getSessionForUser(DOMString username);

  async_iterable<DOMString, Session>;
};

[Exposed=Window]
interface Session {
  readonly attribute DOMString username;
  // ...
};

이터레이터의 동작은 아래처럼 정의될 수 있다:

SessionManager 비동기 이터레이터 iterator의 비동기 이터레이터 초기화 단계:

  1. iterator의 현재 상태를 "아직 시작하지 않음"으로 설정한다.

SessionManager manager와 비동기 이터레이터 iterator에 대해 다음 반복 결과 얻기:

  1. promise를 새 Promise로 둔다.

  2. key를 다음 값으로 둔다(없으면 null):

    만약 iterator의 현재 상태가 "아직 시작하지 않음"이라면

    manager의 열린 세션 중 username이 가장 작은 값(사전순)

    그 외

    manager의 열린 세션 중 iterator의 현재 상태보다 큰 username 중 가장 작은 값(사전순)

    참고: iterator의 현재 상태가 이미 열린 세션에 없을 수도 있다.

  3. key가 null이면:

    1. promise를 반복 종료로 resolve한다.

  4. 그 외:

    1. session을 key에 대응하는 Session 객체로 둔다.

    2. promise를 (username, session)로 resolve한다.

    3. iterator의 현재 상태를 username으로 설정한다.

  5. promise를 반환한다.

자바스크립트 바인딩에서 SessionManager 인터페이스의 인터페이스 프로토타입 객체에는 values 메서드가 있고, 이 함수는 호출 시 다음 값을 반환하는 next 메서드를 가진 비동기 이터레이터 객체를 반환한다. keys와 entries 메서드는 각각 session 객체의 username, username/Session 객체 쌍을 반복한다. %Symbol.asyncIterator% 메서드도 있어서 SessionManager를 for await..of 루프에서 사용할 수 있으며, entries와 같은 값을 반복한다:

// SessionManager 인스턴스를 얻는다.
// 예를 들어 "anna", "brian" 유저 세션이 있다고 가정.
var sm = getSessionManager();

typeof SessionManager.prototype.values;            // "function" 반환
var it = sm.values();                              // values()는 이터레이터 객체 반환
typeof it.next;                                    // "function" 반환

// 아래 루프는 "anna", "brian"을 로그한다.
for await (let username of sm.keys()) {
  console.log(username);
}

// 이것도 동일하다.
for await (let [username, session] of sm) {
  console.log(username);
}

인터페이스에는 복수의 비동기 이터러블 선언이 없어야 한다. 비동기 이터러블 선언이 있는 인터페이스의 상속 인터페이스에도 비동기 이터러블 선언이 있으면 안 된다. 비동기 이터러블 선언이 있는 인터페이스와 그 상속 인터페이스에는 maplike 선언, setlike 선언, 이터러블 선언이 있어서는 안 된다.

비동기 이터러블 선언에 적용 가능한 확장 속성: [CrossOriginIsolated], [Exposed], [SecureContext].

이 확장 속성들은 현재는 적용되지 않으며, 추후 적용되면 예상대로 동작할 것이다.

AsyncIterable ::
    async_iterable < TypeWithExtendedAttributes OptionalType > OptionalArgumentList ;
OptionalArgumentList ::
    ( ArgumentList )
    ε

2.5.11. Maplike 선언

인터페이스는 maplike로 선언될 수 있으며, 이는 인터페이스 본문에 maplike 선언 (ReadWriteMaplike 또는 readonly MaplikeRest에 일치)을 사용해 지정한다.

interface interface_identifier {
  readonly maplike<key_type, value_type>;
  maplike<key_type, value_type>;
};

maplike로 선언된 인터페이스를 구현하는 객체는, 처음에는 비어 있고, 키–값 쌍의 순서 있는 map을 나타내며, 이를 해당 객체의 map 엔트리라고 한다. 키와 값의 타입은 maplike 선언의 꺾쇠 괄호에 지정된다. 키는 반드시 고유해야 한다.

명세 작성자는 map 엔트리의 내용을 수정할 수 있으며, 이는 자바스크립트 코드에서 객체의 내용에 자동으로 반영된다.

maplike 인터페이스는 언어 바인딩에 적절한 map 엔트리 질의 API를 지원한다. readonly 키워드가 없으면, map 엔트리 수정 API도 지원한다.

참고: 자바스크립트 바인딩에서는 map 엔트리와 상호작용하는 API는 자바스크립트 Map 객체와 유사하다. readonly 키워드가 있을 때는 entries, forEach, get, has, keys, values, %Symbol.iterator% 메서드, 그리고 size getter를 포함한다. 읽기–쓰기 maplike일 경우, clear, delete, set 메서드도 포함한다.

maplike 인터페이스에는 "entries", "forEach", "get", "has", "keys", "size", "values" 이름의 속성, 상수, 일반 연산이 존재해서는 안 되며, 상속받은 인터페이스에도 이 이름의 속성, 상수, 일반 연산이 존재해서는 안 된다.

읽기–쓰기 maplike 인터페이스에는 "clear", "delete", "set" 이름의 속성 또는 상수가 존재해서는 안 되며, 상속받은 인터페이스에도 해당 이름의 속성이나 상수가 있어서는 안 된다.

참고: 읽기–쓰기 maplike 인터페이스는 일반 연산으로 "clear", "delete", "set" 이름을 가질 수 있으며, 이는 해당 메서드의 기본 구현을 덮어쓴다(§ 3.7.11 Maplike 선언 참조). 이런 연산이 정의되면, 각 메서드의 기본 구현에 명시된 입력/출력 기대치와 일치해야 한다.

인터페이스에는 복수의 maplike 선언이 없어야 한다. maplike 인터페이스의 상속 인터페이스에도 maplike 선언이 있으면 안 된다. maplike 인터페이스와 상속 인터페이스에는 이터러블 선언, 비동기 이터러블 선언, setlike 선언, 인덱스 프로퍼티 getter가 있어서는 안 된다.

ReadOnlyMember ::
    readonly ReadOnlyMemberRest
ReadOnlyMemberRest ::
    AttributeRest
    MaplikeRest
    SetlikeRest
ReadWriteMaplike ::
    MaplikeRest
MaplikeRest ::
    maplike < TypeWithExtendedAttributes , TypeWithExtendedAttributes > ;

이 명세에서 정의된 확장 속성은 maplike 선언에 적용되지 않는다.

예시 추가 필요.

2.5.12. Setlike 선언

인터페이스는 setlike로 선언될 수 있으며, 이는 인터페이스 본문에 setlike 선언 (ReadWriteSetlike 또는 readonly SetlikeRest에 일치)을 사용해 지정한다.

interface interface_identifier {
  readonly setlike<type>;
  setlike<type>;
};

setlike로 선언된 인터페이스를 구현하는 객체는, 처음에는 비어 있고, 값의 순서 있는 집합을 나타내며, 이를 해당 객체의 set 엔트리라고 한다. 값의 타입은 setlike 선언의 꺾쇠 괄호에 지정된다. 값은 반드시 고유해야 한다.

명세 작성자는 set 엔트리의 내용을 수정할 수 있으며, 이는 자바스크립트 코드에서 객체의 내용에 자동으로 반영된다.

setlike 인터페이스는 언어 바인딩에 적절한 set 엔트리 질의 API를 지원한다. readonly 키워드가 없으면, set 엔트리 수정 API도 지원한다.

참고: 자바스크립트 바인딩에서는 set 엔트리와 상호작용하는 API는 자바스크립트 Set 객체와 유사하다. readonly 키워드가 있을 때는 entries, forEach, has, keys, values, %Symbol.iterator% 메서드, 그리고 size getter를 포함한다. 읽기–쓰기 setlike일 경우, add, clear, delete 메서드도 포함한다.

setlike 인터페이스에는 "entries", "forEach", "has", "keys", "size", "values" 이름의 속성, 상수, 일반 연산이 존재해서는 안 되며, 상속받은 인터페이스에도 이 이름의 속성, 상수, 일반 연산이 존재해서는 안 된다.

읽기–쓰기 setlike 인터페이스에는 "add", "clear", "delete" 이름의 속성 또는 상수가 존재해서는 안 되며, 상속받은 인터페이스에도 해당 이름의 속성이나 상수가 있어서는 안 된다.

참고: 읽기–쓰기 setlike 인터페이스는 일반 연산으로 "add", "clear", "delete" 이름을 가질 수 있으며, 이는 해당 메서드의 기본 구현을 덮어쓴다(§ 3.7.12 Setlike 선언 참조). 이런 연산이 정의되면, 각 메서드의 기본 구현에 명시된 입력/출력 기대치와 일치해야 한다.

인터페이스에는 복수의 setlike 선언이 없어야 한다. setlike 인터페이스의 상속 인터페이스에도 setlike 선언이 있으면 안 된다. setlike 인터페이스와 상속 인터페이스에는 이터러블 선언, 비동기 이터러블 선언, maplike 선언, 인덱스 프로퍼티 getter가 있어서는 안 된다.

ReadOnlyMember ::
    readonly ReadOnlyMemberRest
ReadOnlyMemberRest ::
    AttributeRest
    MaplikeRest
    SetlikeRest
ReadWriteSetlike ::
    SetlikeRest
SetlikeRest ::
    setlike < TypeWithExtendedAttributes > ;

이 명세에서 정의된 확장 속성은 setlike 선언에 적용되지 않는다.

예시 추가 필요.

2.6. 네임스페이스

네임스페이스란, 전역 싱글턴과 관련 동작을 선언하는 정의(Namespace에 일치)입니다.

namespace identifier {
  /* namespace_members... */
};

네임스페이스는 네임스페이스 멤버들의 명세(NamespaceMembers에 일치)입니다. 네임스페이스 멤버란, 네임스페이스 선언의 중괄호 사이에 등장하는 일반 연산, 읽기 전용 일반 속성, 상수입니다. 이 연산과 속성들은 네임스페이스에 패키징되는 동작을 설명합니다.

인터페이스와 마찬가지로, 네임스페이스의 IDL도 부분 네임스페이스 정의(partial Namespace에 일치)를 사용해 여러 부분으로 나눌 수 있습니다. 부분 네임스페이스 정의의 식별자는 네임스페이스 정의의 식별자와 동일해야 합니다. 각 부분 네임스페이스 정의에 등장하는 모든 멤버는 네임스페이스 자체의 멤버로 간주됩니다.

namespace SomeNamespace {
  /* namespace_members... */
};

partial namespace SomeNamespace {
  /* namespace_members... */
};

참고: 부분 인터페이스 정의처럼, 부분 네임스페이스 정의는 명세 편집을 돕기 위한 것으로, 네임스페이스 정의를 문서의 여러 섹션 또는 여러 문서에 걸쳐 분리해 기술할 수 있게 해줍니다.

멤버가 등장하는 순서는 JavaScript 바인딩에서 프로퍼티 열거에 영향을 미칩니다.

인터페이스나 딕셔너리와 다르게, 네임스페이스는 타입을 생성하지 않습니다.

이 명세에서 정의된 확장 속성 중, [CrossOriginIsolated], [Exposed], [SecureContext]만 네임스페이스에 적용할 수 있습니다.

네임스페이스는 반드시 [Exposed] 확장 속성으로 어노테이트해야 합니다.

Partial ::
    partial PartialDefinition
PartialDefinition ::
    interface PartialInterfaceOrPartialMixin
    PartialDictionary
    Namespace
Namespace ::
    namespace identifier { NamespaceMembers } ;
NamespaceMembers ::
    ExtendedAttributeList NamespaceMember NamespaceMembers
    ε
NamespaceMember ::
    RegularOperation
    readonly AttributeRest
    Const

아래 IDL 프래그먼트는 네임스페이스를 정의합니다.

namespace VectorUtils {
  readonly attribute Vector unit;
  double dotProduct(Vector x, Vector y);
  Vector crossProduct(Vector x, Vector y);
};

자바스크립트 구현에서는 전역 VectorUtils 데이터 프로퍼티가 노출되며, 이는 단순 객체(프로토타입은 %Object.prototype%) 이고, 선언된 연산마다 열거 가능한 데이터 프로퍼티, 선언된 속성마다 열거 가능한 읽기 전용 접근자를 가집니다:

Object.getPrototypeOf(VectorUtils);                         // Object.prototype 반환
Object.keys(VectorUtils);                                   // ["dotProduct", "crossProduct"] 반환
Object.getOwnPropertyDescriptor(VectorUtils, "dotProduct"); // { value: <a function>, enumerable: true, configurable: true, writable: true } 반환
Object.getOwnPropertyDescriptor(VectorUtils, "unit");       // { get: <a function>, enumerable: true, configurable: true } 반환

2.7. 딕셔너리

딕셔너리란, Dictionary에 일치하는 정의로, 고정된 순서의 순서 있는 map 데이터 타입을 정의하는 데 사용된다. 이 map의 엔트리들은 딕셔너리 멤버라 하며, 키는 문자열이고 값은 정의에서 지정한 특정 타입이다.

dictionary identifier {
  /* dictionary_members... */
};

딕셔너리 인스턴스는 언어별 표현(예: 해당하는 자바스크립트 객체)에 대한 참조를 유지하지 않는다. 예를 들어, 딕셔너리를 연산에서 반환하면, 현재 딕셔너리 값으로부터 새로운 자바스크립트 객체가 생성된다. 반대로 연산에서 딕셔너리를 인자로 받을 경우, 전달된 자바스크립트 값으로부터 딕셔너리로 한 번만 변환이 수행된다. 딕셔너리를 수정해도 해당 자바스크립트 객체에는 반영되지 않고, 그 반대도 마찬가지다.

딕셔너리는 속성이나 상수의 타입으로 사용될 수 없다.

딕셔너리는 다른 딕셔너리를 상속하도록 정의할 수 있다. 딕셔너리의 식별자 뒤에 콜론과 식별자가 오면, 해당 식별자는 상속받는 딕셔너리를 식별한다. 반드시 딕셔너리를 식별해야 한다.

딕셔너리의 상속 계층에 순환 구조가 있으면 안 된다. 즉, 딕셔너리 A가 자기 자신을 상속하거나, B를 상속하면서 B가 다시 A를 상속하는 방식은 금지된다.

dictionary Base {
  /* dictionary_members... */
};

dictionary Derived : Base {
  /* dictionary_members... */
};

딕셔너리 D의 상속된 딕셔너리들은 D가 직접 또는 간접적으로 상속받는 모든 딕셔너리 집합을 의미한다. D가 다른 딕셔너리를 상속하지 않으면 집합은 비어 있다. 그렇지 않으면, D가 상속한 딕셔너리 E와 E의 상속된 딕셔너리들이 모두 포함된다.

딕셔너리 멤버는 필수로 지정될 수 있다. 이 경우, 해당 멤버에 값을 제공하지 않으면 언어별 값에서 딕셔너리로 변환할 때 오류가 발생한다. 필수가 아닌 멤버는 옵션이다.

딕셔너리 멤버를 필수로 지정하는 것은, 언어별 딕셔너리 표현(예: 연산 인자로 자바스크립트 값을 전달할 때)에서만 효과가 있다. 이외의 경우, 즉 연산에서 딕셔너리를 반환 타입으로만 사용하는 경우 등에는 멤버를 옵션으로 남겨두는 것이 좋다.

타입 D의 딕셔너리 값에는, D와 D의 상속된 딕셔너리들에 정의된 모든 딕셔너리 멤버에 대한 엔트리가 있을 수 있다. 필수 또는 기본값이 지정된 멤버는 반드시 엔트리가 존재한다. 그 외 멤버의 엔트리는 존재할 수도 있고, 아닐 수도 있다.

자바스크립트 바인딩에서는, 딕셔너리 멤버에 해당하는 프로퍼티 값이 undefined면, 해당 프로퍼티가 생략된 것과 동일하게 처리된다. 즉, 필수라면 오류가 발생하고, 기본값이 있으면 그 값이 사용되며, 그 외에는 딕셔너리 값에 해당 엔트리가 존재하지 않는다.

연산 인자 기본값과 마찬가지로, boolean 타입 딕셔너리 멤버의 기본값으로 true를 사용하지 말 것을 강력히 권장한다. 이는 undefined의 기본 변환이 false가 되기를 기대하는 저자에게 혼란을 줄 수 있기 때문이다. [API-DESIGN-PRINCIPLES]

문자열 키를 가진 순서 있는 map은, 모든 엔트리가 딕셔너리 D의 딕셔너리 멤버에 대응하고, 타입이 맞고, 필수 또는 기본값 멤버에 대한 엔트리가 모두 존재하면 암묵적으로 D 타입의 딕셔너리 값으로 간주될 수 있다.

dictionary Descriptor {
  DOMString name;
  sequence<unsigned long> serviceIdentifiers;
};

Descriptor 딕셔너리는 다음과 같이 생성할 수 있다:

  1. identifiers를 « 1, 3, 7 »로 둔다.

  2. «[ "name" → "test", "serviceIdentifiers" → identifiers ]»를 반환한다.

각 딕셔너리 멤버(DictionaryMember에 일치)는 Type에 일치하는 타입 뒤에 식별자가 따라온다(타입 뒤에 identifier 토큰). 이 식별자가 키–값 쌍의 키 이름이다. Type이 식별자 뒤에 ?가 붙으면, 해당 식별자는 인터페이스, 열거형, 콜백 함수, 콜백 인터페이스, 타입 정의 중 하나를 식별해야 한다. ?가 없으면, 위 타입들 중 하나 또는 딕셔너리여야 한다.

딕셔너리 멤버의 타입이 typedef 해석 후 널 허용 타입이면, 내부 타입이 딕셔너리 타입이면 안 된다.

dictionary identifier {
  type identifier;
};

옵션 딕셔너리 멤버의 식별자 뒤에 U+003D(=)와 값(DefaultValue에 일치)이 오면, 해당 멤버의 기본값이 된다. 이 값은 코드나 명세에서 값을 지정하지 않을 경우 기본으로 사용된다.

dictionary identifier {
  type identifier = "value";
};

불리언 리터럴 토큰(true 또는 false), null 토큰, integer 토큰, decimal 토큰, 세 가지 특수 부동소수점 리터럴(Infinity, -Infinity, NaN), string 토큰, [] 또는 {} 토큰 시퀀스가 기본값으로 사용되면, 연산의 옵션 인자 기본값과 같은 방식으로 해석된다.

딕셔너리 멤버 타입이 열거형이면, 기본값은 반드시 열거형의 값 중 하나여야 한다.

딕셔너리 멤버 타입 앞에 required 키워드가 있으면, 해당 멤버는 필수 딕셔너리 멤버로 간주된다.

dictionary identifier {
  required type identifier;
};

딕셔너리 멤버의 타입에는 해당 딕셔너리가 포함되면 안 된다. 타입이 딕셔너리 D를 포함한다는 것은 다음 중 하나라도 참이면 성립한다:

인터페이스와 마찬가지로, 딕셔너리의 IDL도 부분 딕셔너리 정의(partial Dictionary에 일치)를 사용해 여러 부분으로 나눌 수 있다. 부분 딕셔너리 정의의 식별자는 딕셔너리 정의의 식별자와 같아야 한다. 각 부분 딕셔너리 정의에 등장하는 모든 멤버는 딕셔너리 자체의 멤버로 간주된다.

dictionary SomeDictionary {
  /* dictionary_members... */
};

partial dictionary SomeDictionary {
  /* dictionary_members... */
};

참고: 부분 인터페이스 정의와 같이, 부분 딕셔너리 정의는 명세 편집을 돕기 위한 것으로, 딕셔너리 정의를 문서의 여러 섹션이나 여러 문서에 걸쳐 분리할 수 있게 해준다.

딕셔너리의 딕셔너리 멤버 순서는, 상속된 멤버가 비상속 멤버보다 앞에 오고, 한 딕셔너리 정의(부분 딕셔너리 포함) 내 멤버들은 식별자의 유니코드 코드포인트 기준으로 사전순 정렬된다.

사전 값의 항목은 항상 해당하는 사전 멤버의 순서대로 정렬되며, 이들이 설정된 순서와는 무관합니다.

예를 들어, 아래 정의가 있을 때:

dictionary B : A {
  long b;
  long a;
};

dictionary A {
  long c;
  long g;
};

dictionary C : B {
  long e;
  long f;
};

partial dictionary A {
  long h;
  long d;
};

C 타입 딕셔너리 값의 딕셔너리 멤버 순서는 c, d, g, h, a, b, e, f이다.

딕셔너리 멤버는 순서가 필요하다. 왜냐하면 일부 언어 바인딩에서 딕셔너리 값을 플랫폼 객체에 전달할 때, 딕셔너리 멤버를 조회하는 순서에 따라 동작이 달라질 수 있기 때문이다. 예를 들어 아래 인터페이스:

[Exposed=Window]
interface Something {
  undefined f(A a);
};

그리고 자바스크립트 코드:

var something = getSomething();  // Something 인스턴스 얻기
var x = 0;

var dict = { };
Object.defineProperty(dict, "d", { get: function() { return ++x; } });
Object.defineProperty(dict, "c", { get: function() { return ++x; } });

something.f(dict);

딕셔너리 멤버를 조회하는 순서에 따라 값이 달라진다. A의 순서가 c, d이므로, c 값은 1, d 값은 2가 된다.

따라서 항목이 동일한 키와 동일한 값을 갖는 두 사전 값은 해당 항목들이 설정된 순서와 관계없이 동일합니다. 해당 항목들이 설정된 순서와는 무관합니다.

사전 멤버의 식별자는 해당 사전 또는 해당 사전의 상속된 사전에 정의된 다른 사전 멤버의 식별자와 같아서는 안 됩니다.

사전에는 확장 속성이 적용되지 않습니다.

Partial ::
    partial PartialDefinition
PartialDefinition ::
    interface PartialInterfaceOrPartialMixin
    PartialDictionary
    Namespace
Dictionary ::
    dictionary identifier Inheritance { DictionaryMembers } ;
DictionaryMembers ::
    DictionaryMember DictionaryMembers
    ε
DictionaryMember ::
    ExtendedAttributeList DictionaryMemberRest
DictionaryMemberRest ::
    required TypeWithExtendedAttributes identifier ;
    Type identifier Default ;
PartialDictionary ::
    dictionary identifier { DictionaryMembers } ;
Default ::
    = DefaultValue
    ε
DefaultValue ::
    ConstValue
    string
    [ ]
    { }
    null
    undefined
Inheritance ::
    : identifier
    ε

딕셔너리 타입의 한 가지 용도는, 옵션 인자를 연산에 여러 개 제공하면서, 호출 시 인자 순서에 구애받지 않게 하는 것이다. 예를 들어, 다음 IDL 프래그먼트를 보자:

[Exposed=Window]
interface Point {
  constructor();
  attribute double x;
  attribute double y;
};

dictionary PaintOptions {
  DOMString fillPattern = "black";
  DOMString strokePattern;
  Point position;
};

[Exposed=Window]
interface GraphicsContext {
  undefined drawRectangle(double width, double height, optional PaintOptions options);
};

IDL의 자바스크립트 구현에서는, 옵션 PaintOptions 딕셔너리에 Object를 넘길 수 있다:

// GraphicsContext 인스턴스 얻기
var ctx = getGraphicsContext();

// 사각형 그리기
ctx.drawRectangle(300, 200, { fillPattern: "red", position: new Point(10, 10) });

PaintOptions의 멤버는 옵션이다. fillPattern을 생략하면, drawRectangle 정의에서 기본값이 있다고 간주하고 따로 생략 처리 문구를 넣지 않아도 된다. strokePattern과 position 생략 시는 drawRectangle에서 명시적으로 처리해야 한다.

2.8. 예외

예외란 오류를 나타내는 객체 타입으로, 구현체에서 throw 하거나 값처럼 다룰 수 있다. Web IDL에는 명세에서 연산, 속성 등에 참조 또는 throw할 수 있는 여러 기본 예외가 정의되어 있다. 인터페이스에서 DOMException을 상속하여 커스텀 예외 타입도 정의할 수 있다.

단순 예외는 다음 타입 중 하나로 식별된다:

이는 JavaScript의 모든 오류 객체에 해당하지만, 다음은 제외됩니다. AggregateError 및 SuppressedError는 다른 오류를 감싸는 용도로만 설계되었으며, SyntaxError는 JavaScript 파서에서 사용하도록 예약되어 있고, Error는 작성자가 사용하도록 예약되어 있습니다. 각 단순 예외의 의미는 해당 오류 객체의 의미와 JavaScript 명세에서 일치합니다.

두 번째 예외 종류는 DOMException으로, 발생한 오류에 대해 name으로 프로그래밍적으로 상세 정보를 제공한다. name 값은 아래 DOMException 이름 테이블에서 선정된다.

DOMException은 인터페이스 타입이므로 IDL에서 타입으로 사용할 수 있다. 예를 들어 연산의 DOMException 반환 타입으로 선언할 수 있지만, 예외는 반환이 아니라 throw하는 것이므로 이런 패턴은 바람직하지 않다.

세 번째 예외 종류는 DOMException을 상속한 인터페이스이다. 이들은 더 복잡하므로 § 2.8.2 DOMException 파생 인터페이스에서 따로 설명한다.

단순 예외는 타입 이름을 제공해 생성할 수 있다. DOMException은 name 뒤에 DOMException을 제공하여 생성한다. 예외는 throw할 수도 있는데, 이때도 생성할 때와 동일한 정보가 필요하다. 두 경우 모두 예외가 무엇을 의미하는지에 대한 추가 정보를 제공할 수 있으며, 예외 메시지 작성에 유용하다.

예외를 생성하고 throw하는 문구 예시: 단순 예외 TypeError를 throw하려면:

TypeError를 throw한다.

name이 "NotAllowedError"인 DOMException을 throw하려면:

"NotAllowedError" DOMException을 throw한다.

name이 "SyntaxError"인 DOMException을 생성하려면:

object를 새로 생성된 "SyntaxError" DOMException으로 둔다.

name이 "OperationError"인 DOMException으로 promise를 reject하려면:

p를 "OperationError" DOMException으로 reject한다.

예외 메시지에 추가 정보를 포함하는 예시:

"SyntaxError" DOMException을 throw한다. 이 때 주어진 값에 허용되지 않는 후행 공백이 있었다고 명시한다.

이런 추가 컨텍스트는 예외 발생 이유가 명확하지 않을 때(예: 알고리즘 여러 단계에서 "SyntaxError" DOMException을 throw할 때) 구현자에게 도움이 된다. 반면, 예를 들어 사용자가 특정 기능 사용 권한을 제공했는지 검사하고 바로 "NotAllowedError" DOMException을 throw하는 경우에는 메시지 구체화가 필요하지 않다.

예외 생성 및 throw의 실제 동작은 언어 바인딩마다 다르다.

§ 3.14.3 예외 생성 및 throw에서 자바스크립트 바인딩에서 예외 생성 및 throw의 상세 동작을 볼 수 있다.

2.8.1. 기본 DOMException 오류 이름

아래 DOMException 이름 테이블은 기본 DOMException 인터페이스 인스턴스에 허용되는 모든 이름과, 각 이름의 의미 및 레거시 숫자 오류 코드 값을 설명합니다.

DOMException을 상속한 인터페이스(아래 § 2.8.2 DOMException 파생 인터페이스 참고)는 자체 이름을 가지며, 이 테이블에는 포함되지 않습니다.

DOMException을 생성하거나 throw할 때, 명세서는 반드시 이 이름 중 하나를 사용해야 합니다. 만약 명세자가 어떤 이름도 적합하지 않다고 생각되면, 이슈를 등록해 새로운 이름 추가를 논의해야 하며, 커뮤니티가 이런 작업을 조율할 수 있습니다. 새로운 케이스별 이름은, 웹 개발자가 단일 API에서 여러 오류 조건을 구분할 필요가 있을 때만 중요합니다.

DOMException 이름 중 "deprecated"로 표시된 것은 레거시를 위해 남아 있지만, 사용은 권장하지 않습니다.

참고: 여기 정의된 "SyntaxError" DOMException과 JavaScript의 SyntaxError를 혼동하지 마세요. "SyntaxError" DOMException은 웹 API에서 파싱 오류(예: 셀렉터 파싱 등)를 보고하는 데 사용되며, JavaScript SyntaxError는 JS 파서 용도로 예약되어 있습니다. 혼동을 피하기 위해, 항상 "SyntaxError" DOMException 표기를 사용하고, DOMException을 가리킬 때 단순히 SyntaxError라고만 쓰지 마세요. [DOM]

이름 설명 레거시 코드 이름 및 값
"IndexSizeError" 사용 중단됨. 대신 RangeError 사용. INDEX_SIZE_ERR (1)
"HierarchyRequestError" 연산 결과가 잘못된 노드 트리가 될 때. [DOM] HIERARCHY_REQUEST_ERR (3)
"WrongDocumentError" 객체가 잘못된 문서에 있을 때. [DOM] WRONG_DOCUMENT_ERR (4)
"InvalidCharacterError" 문자열에 잘못된 문자가 포함됨. INVALID_CHARACTER_ERR (5)
"NoModificationAllowedError" 객체를 수정할 수 없음. NO_MODIFICATION_ALLOWED_ERR (7)
"NotFoundError" 객체를 여기서 찾을 수 없음. NOT_FOUND_ERR (8)
"NotSupportedError" 연산이 지원되지 않음. NOT_SUPPORTED_ERR (9)
"InUseAttributeError" 속성이 다른 요소에서 이미 사용 중임. [DOM] INUSE_ATTRIBUTE_ERR (10)
"InvalidStateError" 객체가 올바르지 않은 상태임. INVALID_STATE_ERR (11)
"SyntaxError" 문자열이 예상 패턴과 일치하지 않음. SYNTAX_ERR (12)
"InvalidModificationError" 이 방식으로 객체를 수정할 수 없음. INVALID_MODIFICATION_ERR (13)
"NamespaceError" 연산이 Namespaces in XML에 의해 허용되지 않음. [XML-NAMES] NAMESPACE_ERR (14)
"InvalidAccessError" 사용 중단됨. 잘못된 인자에는 TypeError, 지원되지 않는 연산에는 "NotSupportedError" DOMException, 거부된 요청에는 "NotAllowedError" DOMException 사용. INVALID_ACCESS_ERR (15)
"TypeMismatchError" 사용 중단됨. 대신 TypeError 사용. TYPE_MISMATCH_ERR (17)
"SecurityError" 연산이 안전하지 않음. SECURITY_ERR (18)
"NetworkError" 네트워크 오류가 발생함. NETWORK_ERR (19)
"AbortError" 연산이 중단됨. ABORT_ERR (20)
"URLMismatchError" 사용 중단됨. URL_MISMATCH_ERR (21)
"QuotaExceededError" 사용 중단됨. 대신 QuotaExceededError DOMException 파생 인터페이스 사용. QUOTA_EXCEEDED_ERR (22)
"TimeoutError" 연산이 제한 시간을 초과함. TIMEOUT_ERR (23)
"InvalidNodeTypeError" 제공된 노드가 이 연산에 부적합하거나 상위 노드가 부적합함. [DOM] INVALID_NODE_TYPE_ERR (24)
"DataCloneError" 객체를 복제할 수 없음. DATA_CLONE_ERR (25)
"EncodingError" 인코딩(또는 디코딩) 작업이 실패함. —
"NotReadableError" I/O 읽기 작업이 실패함. —
"UnknownError" 알 수 없는 일시적 이유(예: 메모리 부족)로 연산이 실패함. —
"ConstraintError" 트랜잭션의 변이 작업이 제약 조건을 만족하지 않아 실패함. [INDEXEDDB] —
"DataError" 제공된 데이터가 불충분함. —
"TransactionInactiveError" 요청이 현재 활성 상태가 아니거나 종료된 트랜잭션에 대해 실행됨. [INDEXEDDB] —
"ReadOnlyError" "readonly" 트랜잭션에서 변이 작업 시도함. [INDEXEDDB] —
"VersionError" 기존 버전보다 낮은 버전으로 데이터베이스를 열려고 시도함. [INDEXEDDB] —
"OperationError" 연산별 이유로 연산이 실패함. —
"NotAllowedError" 현재 컨텍스트에서 사용자 에이전트 또는 플랫폼에서 요청이 허용되지 않음(예: 사용자가 권한 거부함). —
"OptOutError" 사용자가 해당 프로세스를 거부함. —

2.8.2. DOMException 파생 인터페이스

예외가 DOMException의 name으로 제공되는 정보 외에, 추가로 프로그래밍적으로 조회 가능한 정보를 담아야 할 때, 명세 작성자는 DOMException를 상속하는 인터페이스를 만들 수 있다. 이런 인터페이스는 개발자가 예측 가능한 형태로 다룰 수 있도록 다음 규칙을 따라야 한다:

이 요구로 인해, 이런 인터페이스의 상속된 code 프로퍼티는 항상 0을 반환한다.

DOMException 파생 인터페이스를 생성하거나 throw하려면, 해당 인터페이스 식별자와 추가 정보가 필요하다.

QuotaExceededError 인스턴스를 throw하려면:

QuotaExceededError를 throw한다. quota는 42, requested는 50으로 설정한다.

2.8.3. 미리 정의된 DOMException 파생 인터페이스

이 표준에서는 현재 미리 정의된 DOMException 파생 인터페이스가 하나 있다:

[Exposed=*, Serializable]
interface QuotaExceededError : DOMException {
  constructor(optional DOMString message = "", optional QuotaExceededErrorOptions options = {});

  readonly attribute double? quota;
  readonly attribute double? requested;
};

dictionary QuotaExceededErrorOptions {
  double quota;
  double requested;
};

QuotaExceededError 예외는 할당량을 초과했을 때 throw할 수 있다. 두 개의 속성(quota, requested)을 가지고 있으며, 웹 개발자가 자신의 요청과 할당량 값을 비교할 수 있도록 추가 정보를 제공한다.

이전 버전의 표준에서는 "QuotaExceededError"가 기본 DOMException 오류 이름 중 하나였으나, 이런 정보를 제공할 수 있도록 풀 인터페이스로 승격되었다.

모든 QuotaExceededError 인스턴스는 requested와 quota라는 두 개의 숫자 또는 null 값을 가지며, 최초 값은 모두 null이다.

new QuotaExceededError(message, options) 생성자 단계:
  1. this의 name을 "QuotaExceededError"로 설정한다.

  2. this의 message를 message로 설정한다.

  3. options["quota"]가 있으면:

    1. options["quota"]가 0보다 작으면 RangeError를 throw한다.

    2. this의 quota를 options["quota"]로 설정한다.

  4. options["requested"]가 있으면:

    1. options["requested"]가 0보다 작으면 RangeError를 throw한다.

    2. this의 requested를 options["requested"]로 설정한다.

  5. this 의 quota 가 null이 아니고, this 의 requested 가 null이 아니며, this 의 requested 가 this 의 quota 보다 작으면 RangeError 를 throw한다.

quota getter는 this의 quota를 반환한다.

requested getter는 this의 requested를 반환한다.

QuotaExceededError 인터페이스는 DOMException의 code getter를 상속받으며, 항상 22를 반환한다. 하지만 이 값에 의존하는 것은 권장되지 않는다(QuotaExceededError와 DOMException 모두에서). 대신 name getter를 사용하는 것이 더 낫다.


QuotaExceededError 객체는 직렬화 가능한 객체이다.

직렬화 단계(value, serialized):
  1. DOMException의 직렬화 단계를 value, serialized에 대해 실행한다.

  2. serialized.[[Quota]]를 value의 quota로 설정한다.

  3. serialized.[[Requested]]를 value의 requested로 설정한다.

역직렬화 단계(serialized, value):
  1. DOMException의 역직렬화 단계를 serialized, value에 대해 실행한다.

  2. value의 quota를 serialized.[[Quota]]로 설정한다.

  3. value의 requested를 serialized.[[Requested]]로 설정한다.


QuotaExceededError를 생성하거나 throw할 때, requested와 quota가 모두 null이 아니면서 requested가 quota보다 작으면 안 된다.

2.9. 열거형

열거형이란, Enum에 일치하는 정의로, 타입의 유효 값이 미리 정해진 문자열 집합인 것을 선언한다. 열거형은 DOMString 값이 속성에 할당되거나 연산에 인자로 전달될 때, 가능한 값을 제한하는 데 사용할 수 있다.

enum identifier { "enum", "values" /* , ... */ };

열거형 값은 쉼표로 구분된 string 리터럴 목록으로 지정한다. 열거형 값 목록에는 중복이 있으면 안 된다.

열거형 값은 모두 소문자로 하고, 여러 단어는 대시(-)로 구분하거나 아예 구분하지 않는 것이 강력히 권장된다. 특별한 이유가 없으면 다른 명명 규칙을 사용하지 말 것. 예를 들어, 객체 생성 의미의 값은 "createobject" 또는 "create-object"로 할 수 있다. 관련 API에서 일관성을 위해 단어 구분 방식도 신중히 결정할 것.

열거형 타입 속성에 유효하지 않은 문자열 값을 할당하거나, 연산 인자로 전달하는 경우의 동작은 언어 바인딩에 따라 다르다.

참고: 자바스크립트 바인딩에서는 속성에 잘못된 문자열 값을 할당하면 무시되지만, 다른 맥락(예: 연산 인자)에서는 예외가 throw된다.

이 명세에서 정의된 확장 속성은 열거형에 적용되지 않는다.

Enum ::
    enum identifier { EnumValueList } ;
EnumValueList ::
    string EnumValueListComma
EnumValueListComma ::
    , EnumValueListString
    ε
EnumValueListString ::
    string EnumValueListComma
    ε

아래 IDL 프래그먼트는 열거형을 속성 타입과 연산 인자로 사용한 예시이다:

enum MealType { "rice", "noodles", "other" };

[Exposed=Window]
interface Meal {
  attribute MealType type;
  attribute double size;     // g 단위

  undefined initialize(MealType type, double size);
};

자바스크립트 구현에서는 type 속성이나 initialize 함수 인자에 할당할 수 있는 문자열이 열거형에 명시된 문자열로 제한된다.

var meal = getMeal();                // Meal 인스턴스 얻기

meal.initialize("rice", 200);        // 정상적으로 호출됨

try {
  meal.initialize("sandwich", 100);  // TypeError 발생
} catch (e) {
}

meal.type = "noodles";               // 정상 할당
meal.type = "dumplings";             // 무시됨
meal.type == "noodles";              // true 반환

2.10. 콜백 함수

"Custom DOM Elements" 명세에서는 플랫폼 객체 제공 함수에도 콜백 함수 타입을 사용하고 싶어합니다. 콜백 함수 대신 그냥 "함수"로 이름을 바꿔서 두 가지 용도 모두 명확히 할 수 있을까요?

콜백 함수란, callback CallbackRest에 일치하는 정의로, 함수 타입을 선언하는 데 사용됩니다.

callback identifier = return_type (/* arguments... */);

참고: 유사 이름의 콜백 인터페이스도 참고하세요.

등호 왼쪽의 식별자가 콜백 함수 이름이며, 오른쪽의 반환 타입과 인자 목록(Type 및 ArgumentList)이 함수 시그니처를 정의합니다.

콜백 함수는 상수의 타입으로 사용될 수 없습니다.

콜백 함수에 적용 가능한 확장 속성: [LegacyTreatNonObjectAsNull].

CallbackOrInterfaceOrMixin ::
    callback CallbackRestOrInterface
    interface InterfaceOrMixin
CallbackRest ::
    identifier = Type ( ArgumentList ) ;

아래 IDL 프래그먼트는 연산이 완료될 때 사용자 정의 함수를 호출하는 API의 콜백 함수를 정의한 예시입니다.

callback AsyncOperationCallback = undefined (DOMString status);

[Exposed=Window]
interface AsyncOperations {
  undefined performOperation(AsyncOperationCallback whenFinished);
};

자바스크립트 바인딩에서는 함수 객체가 연산 인자로 전달된다.

var ops = getAsyncOperations();  // AsyncOperations 인스턴스 얻기

ops.performOperation(function(status) {
  window.alert("Operation finished, status is " + status + ".");
});

2.11. 타입 정의

타입 정의(typedef)란, Typedef에 일치하는 정의로, 타입에 새 이름을 선언하는 데 사용됩니다. 이 새 이름은 언어 바인딩에 노출되지 않으며, IDL 내에서 타입을 참조할 때만 약칭으로 쓰입니다.

typedef type identifier;

새 이름을 부여받는 타입은 typedef 키워드 뒤에 지정되며(TypeWithExtendedAttributes에 일치), 그 뒤의 identifier 토큰이 이름이 됩니다.

Type은 동일하거나 다른 typedef의 식별자가 되어서는 안 됩니다.

이 명세에서 정의된 확장 속성은 타입 정의에 적용되지 않습니다.

Typedef ::
    typedef TypeWithExtendedAttributes identifier ;

아래 IDL 프래그먼트는 타입 정의(typedef)를 사용해 긴 시퀀스 타입 대신 짧은 식별자를 쓸 수 있게 하는 예를 보여줍니다.

[Exposed=Window]
interface Point {
  attribute double x;
  attribute double y;
};

typedef sequence<Point> Points;

[Exposed=Window]
interface Widget {
  boolean pointWithinBounds(Point p);
  boolean allPointsWithinBounds(Points ps);
};

2.12. 인터페이스를 구현하는 객체

하나의 IDL 프래그먼트 집합에 대한 구현에서는, 객체가 플랫폼 객체라고 할 수 있습니다.

플랫폼 객체란 인터페이스를 구현하는 객체입니다.

레거시 플랫폼 객체란 [Global] 확장 속성이 없는 인터페이스를 구현하고, 인덱스 프로퍼티 또는 이름 프로퍼티 또는 둘 다를 지원하는 플랫폼 객체입니다.

예를 들어 브라우저에서는, 브라우저가 구현한 DOM 객체들(Node, Document 등 인터페이스 구현)은 페이지 내 자바스크립트에서 웹 페이지 내용을 접근할 수 있게 해주는 플랫폼 객체입니다. 이런 객체들은 C++ 등으로 구현된 특수 객체일 수도 있고, 네이티브 자바스크립트 객체일 수도 있습니다. 어쨌든, 하나의 IDL 프래그먼트 집합에 대한 구현에서는, 모든 플랫폼 객체를 인식할 수 있어야 합니다. 이것은 내부적으로 객체가 플랫폼 객체임을 기록하거나, 객체가 특정 C++ 클래스에서 구현된 것을 감지하는 방식 등으로 이뤄질 수 있습니다. 어떤 방식으로 인식할지는 구현체마다 다릅니다.

시스템 내 다른 객체들은 플랫폼 객체로 취급되지 않습니다. 예를 들어, 브라우저에서 웹 페이지가 자바스크립트 라이브러리를 불러와 DOM Core를 구현한다고 해도, 이 라이브러리에서 Node 인터페이스를 구현해 만든 객체는 브라우저 구현체가 Node를 구현한 플랫폼 객체로 취급되지 않습니다.

반면 콜백 인터페이스는 어떤 자바스크립트 객체로도 구현할 수 있습니다. 이를 통해 웹 API가 저자(사용자) 정의 연산을 호출할 수 있습니다. 예를 들어, DOM Events 구현에서는 EventListener 인터페이스를 구현한 객체를 콜백 등록에 사용할 수 있습니다.

2.13. 타입

이 절에서는 Web IDL이 지원하는 타입, 각 타입에 대응하는 값의 집합 또는 Infra 타입, 그리고 해당 타입의 상수가 어떻게 표현되는지를 나열합니다.

다음 타입은 정수 타입으로 알려져 있습니다: byte, octet, short, unsigned short, long, unsigned long, long long 및 unsigned long long입니다.

다음 타입은 숫자 타입으로 알려져 있습니다: 정수 타입, float, unrestricted float, double 및 unrestricted double입니다.

기본 타입은 bigint, boolean 및 숫자 타입입니다.

문자열 타입은 DOMString, 모든 열거형 타입, ByteString 및 USVString입니다.

버퍼 타입은 ArrayBuffer 및 SharedArrayBuffer입니다.

형식화 배열 타입은 Int8Array, Int16Array, Int32Array, Uint8Array, Uint16Array, Uint32Array, Uint8ClampedArray, BigInt64Array, BigUint64Array, Float16Array, Float32Array, 및 Float64Array입니다.

버퍼 뷰 타입은 DataView 및 형식화 배열 타입입니다.

버퍼 소스 타입은 버퍼 타입 및 버퍼 뷰 타입입니다.

object 타입, 모든 인터페이스 타입 및 모든 콜백 인터페이스 타입은 객체 타입으로 알려져 있습니다.

연산을 호출하거나 속성에 값을 할당하기 위해 언어 바인딩별 타입에서 IDL 타입으로 변환할 때에는, 필요한 모든 변환이 연산 또는 속성 할당에 대해 지정된 기능이 수행되기 전에 완료됩니다. 변환을 수행할 수 없는 경우에는 연산이 실행되지 않거나 속성이 갱신되지 않습니다. 일부 언어 바인딩에서는 타입 변환으로 인해 예외가 발생할 수 있습니다. 이러한 경우 해당 예외는 연산을 호출하거나 속성에 값을 할당하려고 시도한 코드로 전파됩니다.

Type ::
    SingleType
    UnionType Null
TypeWithExtendedAttributes ::
    ExtendedAttributeList Type
SingleType ::
    DistinguishableType
    any
    PromiseType
UnionType ::
    ( UnionMemberType or UnionMemberType UnionMemberTypes )
UnionMemberType ::
    ExtendedAttributeList DistinguishableType
    UnionType Null
UnionMemberTypes ::
    or UnionMemberType UnionMemberTypes
    ε
DistinguishableType ::
    PrimitiveType Null
    StringType Null
    identifier Null
    sequence < TypeWithExtendedAttributes > Null
    async_sequence < TypeWithExtendedAttributes > Null
    object Null
    symbol Null
    BufferRelatedType Null
    FrozenArray < TypeWithExtendedAttributes > Null
    ObservableArray < TypeWithExtendedAttributes > Null
    RecordType Null
    undefined Null
ConstType ::
    PrimitiveType
    identifier
PrimitiveType ::
    UnsignedIntegerType
    UnrestrictedFloatType
    boolean
    byte
    octet
    bigint
UnrestrictedFloatType ::
    unrestricted FloatType
    FloatType
FloatType ::
    float
    double
UnsignedIntegerType ::
    unsigned IntegerType
    IntegerType
IntegerType ::
    short
    long OptionalLong
OptionalLong ::
    long
    ε
StringType ::
    ByteString
    DOMString
    USVString
PromiseType ::
    Promise < Type >
RecordType ::
    record < StringType , TypeWithExtendedAttributes >
Null ::
    ?
    ε

2.13.1. any

any 타입은 모든 다른 non-union 타입의 합집합입니다.

any 타입은 각 값이 특정 non-any 타입과 연결되어 있다는 점에서 discriminated union 타입과 유사합니다. 예를 들어, any 타입의 한 값은 unsigned long 150이고, 또 다른 값은 long 150입니다. 이 둘은 서로 다른 값입니다.

any 값의 특정 타입은 특정 타입이라고 합니다. (union 타입의 값도 특정 타입을 가집니다.)

2.13.2. undefined

undefined 타입은 고유한 값을 하나만 가집니다.

undefined 상수 값은 IDL에서 undefined 토큰으로 표현됩니다.

undefined 타입은 어떤 경우에도(연산, 콜백 함수, 생성자 연산 등) 인자 타입이나, 딕셔너리 멤버 타입(직접 또는 union 내)으로 사용해서는 안 됩니다. 대신 옵션 인자나, non-필수 딕셔너리 멤버를 사용하세요.

참고: 이 값은 이전에는 void로 표기되었으며, 사용 방식이 더 제한적이었습니다.

2.13.3. boolean

boolean 타입은 불리언과 대응됩니다.

boolean 상수 값은 IDL에서 true와 false 토큰으로 표현됩니다.

2.13.4. byte

byte 타입은 8비트 부호 있는 정수와 대응됩니다.

byte 상수 값은 IDL에서 integer 토큰으로 표현됩니다.

2.13.5. octet

octet 타입은 8비트 부호 없는 정수와 대응됩니다.

octet 상수 값은 IDL에서 integer 토큰으로 표현됩니다.

2.13.6. short

short 타입은 16비트 부호 있는 정수와 대응됩니다.

short 상수 값은 IDL에서 integer 토큰으로 표현됩니다.

2.13.7. unsigned short

unsigned short 타입은 16비트 부호 없는 정수와 대응됩니다.

unsigned short 상수 값은 IDL에서 integer 토큰으로 표현됩니다.

2.13.8. long

long 타입은 32비트 부호 있는 정수와 대응됩니다.

long 상수 값은 IDL에서 integer 토큰으로 표현됩니다.

2.13.9. unsigned long

unsigned long 타입은 32비트 부호 없는 정수와 대응됩니다.

unsigned long 상수 값은 IDL에서 integer 토큰으로 표현됩니다.

2.13.10. long long

long long 타입은 64비트 부호 있는 정수와 대응됩니다.

long long 상수 값은 IDL에서 integer 토큰으로 표현됩니다.

2.13.11. unsigned long long

unsigned long long 타입은 64비트 부호 없는 정수와 대응됩니다.

unsigned long long 상수 값은 IDL에서 integer 토큰으로 표현됩니다.

2.13.12. float

float 타입은 부동소수점 숫자 타입으로, 유한한 단정밀도 32비트 IEEE 754 부동소수점 숫자 집합에 대응합니다. [IEEE-754]

float 상수 값은 IDL에서 decimal 토큰으로 표현됩니다.

32비트 부동소수점 타입을 특별히 써야 할 이유가 없다면, double을 float 대신 사용하는 것이 좋습니다. double이 표현할 수 있는 값 집합이 JavaScript Number와 더 유사하기 때문입니다.

2.13.13. unrestricted float

unrestricted float 타입은 부동소수점 숫자 타입으로, 모든 가능한 단정밀도 32비트 IEEE 754 부동소수점 값(유한, 무한 및 NaN)을 포함합니다. [IEEE-754]

unrestricted float 상수 값은 IDL에서 decimal 토큰으로 표현됩니다.

2.13.14. double

double 타입은 부동소수점 숫자 타입으로, 유한한 배정밀도 64비트 IEEE 754 부동소수점 숫자 집합에 대응합니다. [IEEE-754]

double 상수 값은 IDL에서 decimal 토큰으로 표현됩니다.

2.13.15. unrestricted double

unrestricted double 타입은 부동소수점 숫자 타입으로, 모든 가능한 배정밀도 64비트 IEEE 754 부동소수점 값(유한, 무한 및 NaN)을 포함합니다. [IEEE-754]

unrestricted double 상수 값은 IDL에서 decimal 토큰으로 표현됩니다.

2.13.16. bigint

bigint 타입은 범위가 제한되지 않은 임의의 정수 타입입니다.

bigint 상수 값은 IDL에서 integer 토큰으로 표현됩니다.

2.13.17. DOMString

DOMString 타입은 문자열과 대응됩니다.

참고: null은 DOMString 타입의 값이 아닙니다. null을 허용하려면 널 허용 DOMString, 즉 IDL에서 DOMString?을 사용해야 합니다.

참고: DOMString 값에는 매치되지 않는 서로게이트 코드 포인트가 포함될 수 있습니다. 이를 원하지 않는 경우 USVString을 사용하세요.

IDL에서는 DOMString 상수 값을 표현할 방법이 없습니다. 다만 DOMString 딕셔너리 멤버 기본값이나 연산 옵션 인자 기본값에는 문자열 리터럴 토큰의 값을 사용할 수 있습니다.

2.13.18. ByteString

ByteString 타입은 바이트 시퀀스에 대응합니다.

IDL에서는 상수 ByteString 값을 나타낼 방법이 없지만, ByteString 사전 멤버의 기본값 및 연산의 선택적 인수 기본값은 string 리터럴의 값으로 설정할 수 있습니다.

명세에서는 ByteString을 HTTP와 같이 바이트와 문자열을 서로 바꾸어 사용하는 프로토콜과 상호 작용하는 경우에만 사용해야 합니다. 일반적으로 문자열은 DOMString 값으로 나타내야 하며, 문자열의 값이 항상 ASCII 또는 어떤 8비트 문자 인코딩에 속할 것으로 예상되는 경우에도 마찬가지입니다. octet 또는 시퀀스나 고정 배열에 byte 요소를 사용하거나, Uint8Array, 또는 Int8Array를 사용하여 8비트 데이터를 보관해야 하며, ByteString을 사용해서는 안 됩니다.

2.13.19. USVString

USVString 타입은 스칼라 값 문자열에 대응합니다. 문맥에 따라 이들은 코드 단위의 시퀀스 또는 스칼라 값의 시퀀스로 취급할 수 있습니다.

IDL에서는 상수 USVString 값을 나타낼 방법이 없지만, USVString 사전 멤버의 기본값 및 연산의 선택적 인수 기본값은 string 리터럴의 값으로 설정할 수 있습니다.

명세서는 USVString을 텍스트 처리 API에서 스칼라 값 문자열이 필요한 경우에만 써야 합니다. 대부분의 문자열 사용 API에서는 DOMString을 써야 하며, 해당 문자열의 코드 유닛을 해석하지 않습니다. 헷갈릴 경우 DOMString을 사용하세요.

2.13.20. object

object 타입은 가능한 모든 non-null 객체 참조 집합에 대응합니다.

IDL에서는 object 상수 값을 표현할 방법이 없습니다.

모든 객체 참조와 null 값을 포함하는 타입을 지정하려면 널 허용 타입 object?를 사용하세요.

2.13.21. symbol

symbol 타입은 모든 가능한 심볼 값 집합에 대응합니다. 심볼 값은 불투명하며, object 값은 아니지만 고유성(자기 자신과만 같음)을 가집니다.

IDL에서는 symbol 상수 값을 표현할 방법이 없습니다.

2.13.22. 인터페이스 타입

식별자가 인터페이스를 지정하면, 해당 인터페이스를 구현하는 non-null 객체 참조의 집합을 타입으로 참조합니다.

인터페이스 타입의 IDL 값은 객체 참조로 표현됩니다.

특정 인터페이스 타입에 대한 상수 객체 참조 값을 IDL에서 표현할 방법은 없습니다.

해당 인터페이스를 구현하는 객체 참조와 null을 모두 포함하는 타입을 지정하려면 널 허용 타입을 사용하세요.

2.13.23. 콜백 인터페이스 타입

식별자가 콜백 인터페이스를 지정하면, 모든 가능한 non-null 객체 참조 집합을 타입으로 참조합니다.

콜백 인터페이스 타입의 IDL 값은 객체 참조와 콜백 컨텍스트의 튜플로 표현됩니다. 콜백 컨텍스트는 언어 바인딩별 값이며, 객체 참조를 IDL 값으로 변환할 때의 실행 컨텍스트 정보를 저장하는 데 사용됩니다.

참고: 자바스크립트 객체에서는 콜백 컨텍스트에 Object 값이 IDL 콜백 인터페이스 타입 값으로 변환될 때의 incumbent settings object 참조가 저장됩니다. § 3.2.16 Callback interface types 참고.

특정 콜백 인터페이스 타입에 대한 상수 객체 참조 값을 IDL에서 표현할 방법은 없습니다.

모든 객체 참조와 null을 포함하는 타입을 지정하려면 널 허용 타입을 사용하세요.

2.13.24. 딕셔너리 타입

식별자가 딕셔너리를 지정하면, 해당 딕셔너리 정의를 따르는 모든 딕셔너리 집합을 타입으로 참조합니다.

순서 있는 맵의 리터럴 문법도, 맵이 특정 딕셔너리 타입 인스턴스로 간주된다는 게 문맥에서 명확하다면 딕셔너리 표현에 사용할 수 있습니다. 그러나 IDL 프래그먼트 내에 상수 딕셔너리 값을 표현하는 방법은 없습니다.

2.13.25. 열거형 타입

식별자가 열거형을 식별하는 경우 그 식별자는 값이 문자열 집합(코드 단위의 시퀀스이며, DOMString과 같음)인 타입을 참조하는 데 사용되며, 이 문자열들은 열거형의 값입니다.

DOMString과 마찬가지로, IDL에서는 상수 열거형 값을 나타낼 방법이 없지만, 열거형 타입의 사전 멤버 기본 값 및 연산의 선택적 인수 기본값은 string 리터럴의 값으로 설정할 수 있습니다.

2.13.26. 콜백 함수 타입

식별자가 콜백 함수를 지정하면, 해당 시그니처의 함수 객체 참조 집합을 타입으로 참조합니다.

참고: [LegacyTreatNonObjectAsNull] 확장 속성이 콜백 함수 정의에 지정된 경우, 함수가 아닌 객체 참조도 값이 될 수 있습니다.

콜백 함수 타입의 IDL 값은 객체 참조와 콜백 컨텍스트의 튜플로 표현됩니다.

참고: 콜백 인터페이스 타입과 마찬가지로, 콜백 컨텍스트는 자바스크립트 Object 값이 IDL 콜백 함수 타입 값으로 변환될 때의 incumbent settings object 참조를 저장하는 데 쓰입니다. § 3.2.19 Callback function types 참고.

IDL에서는 콜백 함수 상수 값을 표현할 방법이 없습니다.

2.13.27. 널 허용 타입 — T?

널 허용 타입은 기존 타입(이를 내부 타입이라 함)에서 null 값을 추가로 허용하는 IDL 타입입니다. 널 허용 타입은 IDL에서 기존 타입 뒤에 U+003F(?)를 붙여 표기합니다. 내부 타입은 다음 중 하나가 아니어야 합니다:

참고: 딕셔너리 타입은 일반적으로 널 허용일 수 있지만, 연산 인수 또는 딕셔너리 멤버의 타입으로 사용되는 경우에는 널 허용일 수 없습니다.

임의의 타입 또는 타입 범주 X에 대해, 잠재적으로 널 허용 X는 X이거나 널 허용 타입이며, 그 내부 타입은 X입니다.

IDL에서 널 허용 타입 상수 값은 해당 내부 타입의 상수 값과 같은 방식으로 표현되거나 null 토큰으로 표현됩니다.

예를 들어, true, false, null 값을 허용하는 타입은 boolean?으로 표기합니다:

[Exposed=Window]
interface NetworkFetcher {
  undefined get(optional boolean? areWeThereYet = false);
};

다음 인터페이스에는 두 개의 속성이 있습니다. 하나는 DOMString 또는 null 값을 가질 수 있고, 다른 하나는 Node 객체 참조 또는 null 값을 가질 수 있습니다:

[Exposed=Window]
interface Node {
  readonly attribute DOMString? namespaceURI;
  readonly attribute Node? parentNode;
  // ...
};

2.13.28. 시퀀스 타입 — sequence<T>

sequence<T> 타입은 (길이가 0일 수도 있는) 리스트로, 각 값이 T 타입인 리스트 타입입니다.

시퀀스는 항상 값으로 전달됩니다. 시퀀스가 어떤 객체로 표현되는 언어 바인딩에서는, 시퀀스를 플랫폼 객체에 전달해도 해당 객체에 시퀀스 참조가 남지 않습니다. 마찬가지로 플랫폼 객체에서 반환된 시퀀스도 복사본이며, 이를 수정해도 플랫폼 객체에는 영향을 미치지 않습니다.

리스트의 리터럴 문법도, 리스트가 시퀀스 타입 인스턴스로 간주된다는 게 문맥에서 명확하다면 시퀀스 표현에 사용할 수 있습니다. 하지만 IDL 프래그먼트 내에 상수 시퀀스 값을 표현하는 방법은 없습니다.

시퀀스는 속성이나 상수 타입으로 사용할 수 없습니다.

참고: 이 제한은 명세 작성자와 API 사용자에게 시퀀스가 참조가 아닌 복사본으로 전달된다는 점을 명확히 하기 위한 것입니다. 시퀀스 타입의 속성 대신, 시퀀스를 get/set하는 연산을 쌍으로 제공하는 것이 좋습니다.

어떤 리스트도, 그 항목이 모두 T 타입이면 암묵적으로 sequence<T>로 간주할 수 있습니다.

2.13.29. 비동기 시퀀스 타입 — async_sequence<T>

async_sequence 타입은 T 타입 값을 비동기적으로 이터레이션할 수 있는(무한 가능성 포함) 객체 참조 집합을 타입으로 하는 파라미터화 타입입니다.

시퀀스와 달리, 비동기 시퀀스는 고정 길이 리스트가 아니라 모든 값이 미리 알려진 상태가 아닙니다. async_sequence로 생성된 비동기 이터러블 시퀀스는 lazy하며, 값은 이터레이션 중에만 비동기적으로 생성될 수 있으므로, 값이나 길이는 시퀀스 생성 시점에 알 수 없습니다.

언어 바인딩에서 async_sequence가 객체로 표현되는 경우 참조로 전달됩니다. 즉, async_sequence를 플랫폼 객체에 전달하면 해당 객체에 참조가 남습니다. 플랫폼 객체에서 반환된 async_sequence도 동일 객체에 대한 참조이며, 이를 수정하면 플랫폼 객체에 영향을 미칩니다. 이는 항상 값으로 전달되는 시퀀스와는 다릅니다.

참고: async_sequence는 IDL에서 생성할 수 없습니다. 연산에서 반환하거나 딕셔너리 멤버 타입으로 쓸 경우, async_sequence는 호스트 환경에서 생성되어 언어 바인딩을 통해 IDL 타입으로 변환된 것입니다. 연산에서 async_sequence를 반환하는 대신, 인터페이스를 반환하고 그 인터페이스에 비동기 이터러블 선언을 둬야 할 수 있습니다.

async_sequence는 속성이나 상수 타입으로 사용할 수 없습니다.

IDL에서는 async_sequence 값을 표현할 방법이 없습니다.

2.13.30. 레코드 타입 — record<K, V>

레코드 타입은 값이 순서가 있는 맵인 매개변수화된 타입이며, 키는 K의 인스턴스이고 값은 V의 인스턴스입니다. K는 다음 중 하나여야 합니다. DOMString, USVString, 또는 ByteString.

순서가 있는 맵의 리터럴 구문은 문맥상 해당 맵이 레코드로 취급된다는 것이 암묵적으로 이해되는 경우 레코드를 나타내는 데에도 사용할 수 있습니다. 그러나 IDL 조각 내부에서 상수 레코드 값을 나타낼 방법은 없습니다.

레코드는 항상 값으로 전달됩니다. 레코드가 어떤 종류의 객체로 표현되는 언어 바인딩에서 레코드를 플랫폼 객체에 전달해도 해당 객체가 레코드에 대한 참조를 유지하게 되지는 않습니다. 마찬가지로 플랫폼 객체에서 반환된 모든 레코드는 복사본이며, 여기에 가한 수정 사항은 플랫폼 객체에 표시되지 않습니다.

레코드는 속성 또는 상수의 타입으로 사용해서는 안 됩니다.

모든 순서가 있는 맵은 다음 조건을 충족하는 한 암묵적으로 record<K, V>로 취급할 수 있습니다. 해당 맵에는 항목만 포함되어야 하며, 그 키는 모두 K 타입이고 그 값은 모두 V 타입이어야 합니다.

2.13.31. 프라미스 타입 — Promise<T>

프라미스 타입은 파라미터화된 타입으로, 값이 비동기 작업의 결과를 나중에 받을 수 있는 “자리 표시자” 객체 참조입니다. 자세한 프라미스 객체 의미는 JavaScript 명세 section 25.4 참고.

프라미스 타입은 널 허용이 아니지만, T는 널 허용일 수 있습니다.

IDL에서는 프라미스 값을 표현할 방법이 없습니다.

2.13.32. 유니온 타입

유니온 타입은 값 집합이 두 개 이상의 타입 값 집합의 합집합이 되는 타입입니다. 유니온 타입(UnionType에 일치)은 타입들을 or로 구분해 괄호로 감싸 표기합니다. 유니온 타입을 구성하는 타입들을 유니온의 멤버 타입이라 합니다.

예를 들어 (Node or DOMString) 또는 (double or sequence<double>)처럼 쓸 수 있습니다. 유니온 타입 전체에 ?를 붙일 때는 닫는 괄호 뒤에 붙여 (Node or DOMString)?처럼 표기합니다.

유니온 타입의 멤버 타입은 중첩된 유니온 타입 안까지 내려가지 않습니다. 예를 들어 (double or (sequence<long> or Event) or (Node or DOMString)?)의 멤버 타입은 double, (sequence<long> or Event), (Node or DOMString)?입니다.

any 타입처럼, 유니온 타입 값도 특정 타입을 가지며, 이는 해당 값과 일치하는 멤버 타입입니다.

유니언 타입의 평탄화된 멤버 타입은, 경우에 따라 주석이 지정될 수 있으며, 다음과 같이 결정되는 타입의 집합입니다:

  1. T를 유니언 타입으로 둡니다.

  2. S를 ∅로 초기화합니다.

  3. T의 각 멤버 타입 U에 대해:

    1. U가 주석이 지정된 타입인 경우, U를 U의 내부 타입으로 설정합니다.

    2. U가 널 허용 타입인 경우, U를 U의 내부 타입으로 설정합니다.

    3. U가 유니언 타입인 경우, S에 U의 평탄화된 멤버 타입을 추가합니다.

    4. 그렇지 않으면, U는 유니언 타입이 아닙니다. U를 S에 추가합니다.

  4. S를 반환합니다.

참고: 예를 들어, 유니온 타입 (Node or (sequence<long> or Event) or (XMLHttpRequest or DOMString)? or sequence<(sequence<double> or NodeList)>)의 평탄화된 멤버 타입은 Node, sequence<long>, Event, XMLHttpRequest, DOMString, sequence<(sequence<double> or NodeList)>입니다.

널 허용 멤버 타입의 수는 유니언 타입에 대해 다음과 같이 결정되는 정수입니다:

  1. T를 유니언 타입으로 둡니다.

  2. n을 0으로 초기화합니다.

  3. T의 각 멤버 타입 U에 대해:

    1. U가 널 허용 타입인 경우:

      1. n을 n + 1로 설정합니다.

      2. U를 U의 내부 타입으로 설정합니다.

    2. U가 유니언 타입인 경우:

      1. m을 U의 널 허용 멤버 타입의 수로 둡니다.

      2. n을 n + m으로 설정합니다.

  4. n을 반환합니다.

any 타입은 유니언 멤버 타입으로 사용해서는 안 됩니다.

널 허용 멤버 타입의 수는 유니언 타입에서 반드시 0 또는 1이어야 하며, 1인 경우 유니언 타입의 딕셔너리 타입이 평탄화된 멤버 타입에도 있어서는 안 됩니다.

타입이 다음 조건을 충족하면 널 허용 타입을 포함합니다:

유니언 타입에 있는 평탄화된 멤버 타입의 각 쌍, T와 U는 반드시 구별 가능해야 합니다.

bigint와 숫자 타입의 유니언을 만들 수 있습니다. 그러나 이는 일반적으로 값을 사용하는 대신 형식을 지정하는 NumberFormat과 같은 인터페이스에만 사용하도록 의도된 것입니다. 계산에 값을 사용하는 것이 아닙니다. 이러한 유니언을 받아들인 다음 숫자 타입의 값을 bigint로 변환하여 추가로 처리하는 것은 적절하지 않습니다. 이는 정밀도 오류를 발생시킬 위험이 있기 때문입니다. 이 기능을 사용하기 전에 이슈를 제출해 주시기 바랍니다.

타입이 다음 조건을 충족하면 undefined를 포함합니다:

IDL에서 유니언 타입 상수 값은 해당 멤버 타입의 상수 값과 동일한 방식으로 표현됩니다.

UnionType ::
    ( UnionMemberType or UnionMemberType UnionMemberTypes )
UnionMemberType ::
    ExtendedAttributeList DistinguishableType
    UnionType Null
UnionMemberTypes ::
    or UnionMemberType UnionMemberTypes
    ε
DistinguishableType ::
    PrimitiveType Null
    StringType Null
    identifier Null
    sequence < TypeWithExtendedAttributes > Null
    async_sequence < TypeWithExtendedAttributes > Null
    object Null
    symbol Null
    BufferRelatedType Null
    FrozenArray < TypeWithExtendedAttributes > Null
    ObservableArray < TypeWithExtendedAttributes > Null
    RecordType Null
    undefined Null

2.13.33. 주석 타입

특정 확장 속성을 기존 타입에 지정하면 추가 타입을 만들 수 있습니다. 이러한 타입을 주석 타입이라 하며, 이들이 주석을 다는 타입을 내부 타입이라 합니다.

[Clamp] long은 주석 타입을 정의합니다. 이 타입은 내부 타입 long의 동작을 기반으로 하지만, [Clamp] 확장 속성에 지정된 대로 동작이 수정됩니다.

아래 확장 속성들이 타입에 적용 가능합니다: [AllowResizable], [AllowShared], [Clamp], [EnforceRange], 그리고 [LegacyNullToEmptyString].

타입에 연관된 확장 속성은 IDL 타입 type에 대해 다음과 같이 결정합니다:
  1. extended attributes를 새로운 빈 집합으로 둡니다.

  2. type이 Type이고, 바로 다음 내부에 있는 TypeWithExtendedAttributes 생성 규칙에 해당한다면, 추가를 사용하여 각 확장 속성 중 생성 규칙의 ExtendedAttributeList에 있는 각각을 extended attributes에 추가합니다.

    [Exposed=Window]
    interface I {
        attribute [XAttr] long attrib;
        undefined f1(sequence<[XAttr] long> arg);
        undefined f2(optional [XAttr] long arg);
    
        maplike<[XAttr2] DOMString, [XAttr3] long>;
    };
    
    dictionary D {
        required [XAttr] long member;
    };
    
  3. type이 멤버 타입이고 유니언 타입 U의 멤버라면, 추가를 사용하여 각 연결된 확장 속성 U의 것을 extended attributes에 추가합니다.

    [Exposed=Window]
    interface I {
        attribute [XAttr] (long or Node) attrib;
    };
    
  4. type이 내부 타입이고 널 허용 타입 N의 것이라면, 추가를 사용하여 각 연결된 확장 속성 N의 것을 extended attributes에 추가합니다.

    [Exposed=Window]
    interface I {
        attribute [XAttr] long? attrib;
    };
    
  5. type이 인수 A의 타입이고 해당 인수가 optional 키워드로 선언되지 않았다면, 추가를 사용하여 extended attributes에 다음의 모든 확장 속성 중 ExtendedAttributeList에 있으며 A의 Argument 생성 규칙에 속하고 타입에 적용 가능한 것들을 추가합니다.

    [Exposed=Window]
    interface I {
        undefined f([XAttr] long attrib);
    };
    

    [XAttr]이 다음 조건을 충족하는 경우에만 이것이 이 단계의 예임에 유의하십시오. 즉, 타입에 적용 가능해야 합니다. 그렇지 않으면 [XAttr]은 인수에 적용되는 것이며, 인수의 타입에는 적용되지 않습니다.

  6. type이 딕셔너리 멤버 M의 타입이고 해당 멤버가 필수가 아니라면, 추가를 사용하여 extended attributes에 다음의 모든 확장 속성 중 ExtendedAttributeList에 있으며 M의 DictionaryMember 생성 규칙에 속하고 타입에 적용 가능한 것들을 추가합니다.

    dictionary D {
        [XAttr] long member;
    };
    

    [XAttr]이 다음 조건을 충족하는 경우에만 이것이 이 단계의 예임에 유의하십시오. 즉, 타입에 적용 가능해야 합니다. 그렇지 않으면 [XAttr]은 딕셔너리 멤버에 적용되는 것이며, 멤버의 타입에는 적용되지 않습니다.

  7. type이 typedef인 경우, 추가를 사용하여 연결된 확장 속성 중 새 이름이 부여되는 타입과 연결된 것을 extended attributes에 추가합니다.

    typedef [XAttr] long xlong;
    
  8. extended attributes를 반환합니다.

어떤 타입에 대해서도, 그 타입과 연결된 확장 속성은 반드시 확장 속성 중 타입에 적용 가능한 것만 포함해야 합니다.

2.13.34. 버퍼 소스 타입

데이터 버퍼나 버퍼 뷰 객체에 대한 모든 non-null 참조 집합에 대응하는 타입들이 있습니다. 아래 표는 각 타입과 해당 타입이 표현하는 버퍼/뷰 종류를 나타냅니다.

타입 버퍼 종류
ArrayBuffer 고정된 바이트 수의 버퍼를 가리키는 포인터(널 가능)를 가진 객체
SharedArrayBuffer 고정된 바이트 수의 공유 버퍼를 가리키는 포인터(널 불가)를 가진 객체
DataView 임의 오프셋에서 정수, 부동소수점 값을 타입별로 접근할 수 있는 버퍼 타입 인스턴스의 뷰
Int8Array 버퍼 타입 인스턴스를 주어진 비트 크기의 2의 보수 부호 있는 정수 배열로 노출하는 뷰
Int16Array
Int32Array
BigInt64Array
Uint8Array 버퍼 타입 인스턴스를 주어진 비트 크기의 부호 없는 정수 배열로 노출하는 뷰
Uint16Array
Uint32Array
BigUint64Array
Uint8ClampedArray 버퍼 타입 인스턴스를 8비트 부호 없는 정수 배열로 노출하며, 값은 클램프 변환됨
Float16Array 버퍼 타입 인스턴스를 지정된 비트 크기의 IEEE 754 부동소수점 숫자 배열로 노출하는 뷰; Float16Array는 ECMAScript 제안 [PROPOSAL-FLOAT16ARRAY]에 해당함.
Float32Array
Float64Array

참고: 이 타입들은 모두 JavaScript에서 정의된 클래스에 해당합니다.

IDL에서는 이러한 타입의 상수 값을 표현할 방법이 없습니다.

명세 산문(prose) 수준에서, IDL 버퍼 소스 타입은 단순히 객체 참조입니다. 버퍼 내부 바이트를 조회/조작하려면 명세 산문에서 § 3.2.26 버퍼 소스 타입 알고리즘을 사용해야 합니다.

BufferRelatedType ::
    ArrayBuffer
    SharedArrayBuffer
    DataView
    Int8Array
    Int16Array
    Int32Array
    Uint8Array
    Uint16Array
    Uint32Array
    Uint8ClampedArray
    BigInt64Array
    BigUint64Array
    Float16Array
    Float32Array
    Float64Array

2.13.35. 불변 배열 타입 — FrozenArray<T>

불변 배열 타입은 파라미터화된 타입으로, 값이 고정 길이의 수정 불가 값 배열을 가진 객체 참조입니다. 배열의 각 값은 T 타입입니다.

불변 배열 타입은 인터페이스에 정의된 일반 속성이나 static 속성 타입으로만 사용해야 합니다.

다음 IDL 프래그먼트는 두 개의 불변 배열 속성이 있는 인터페이스를 정의합니다. 하나는 읽기 전용이고 하나는 읽기 전용이 아닙니다.
[Exposed=Window]
interface PersonalPreferences {
    readonly attribute FrozenArray<DOMString> favoriteColors;
    attribute FrozenArray<DOMString> favoriteFoods;

    undefined randomizeFavoriteColors();
};

이 속성들의 동작 정의 예시:

각 PersonalPreferences는 favorite colors(FrozenArray<DOMString>)를 갖고, 초기값은 « "purple", "aquamarine" »로 불변 배열 생성 결과입니다.

각 PersonalPreferences는 favorite foods(FrozenArray<DOMString>)도 갖고, 초기값은 빈 리스트로 불변 배열 생성 결과입니다.

favoriteColors getter 단계는 this의 favorite colors를 반환합니다.

favoriteFoods getter 단계는 this의 favorite foods를 반환합니다.

favoriteFoods setter 단계는 this의 favorite foods를 지정 값으로 설정합니다.

randomizeFavoriteColors() 메서드 단계는:

  1. newFavoriteColors를 임의로 선택한 색상 2개의 문자열 리스트로 둔다.

  2. this의 favorite colors를 불변 배열 생성(newFavoriteColors) 결과로 설정.

FrozenArray<T> 값은 참조이므로, 시퀀스 타입처럼 값으로 전달되는 리스트와는 다릅니다.

IDL에서는 불변 배열 상수 값을 표현할 방법이 없습니다.

2.13.36. 관찰 배열 타입 — ObservableArray<T>

관찰 배열 타입은 파라미터화된 타입으로, 값이 T 타입 객체의 변경 가능한 리스트와, 저자 코드가 리스트를 수정할 때 실행되는 동작을 결합한 객체 참조입니다.

파라미터화 타입 T는 딕셔너리 타입, 시퀀스 타입, 레코드 타입, 관찰 배열 타입이 될 수 없습니다. 하지만 T는 널 허용일 수 있습니다.

시퀀스 타입과 불변 배열 타입처럼, 관찰 배열 타입도 자바스크립트 배열 타입을 감싸며 추가 의미를 부여합니다.

관찰 배열 타입은 인터페이스에 정의된 일반 속성 타입으로만 사용해야 합니다.

관찰 배열 속성에는 명세 저자가 다음 알고리즘을 정의할 수 있습니다:

이 두 알고리즘은 모두 선택적이며, 정의되지 않으면 기본 동작은 아무것도 하지 않는 것입니다. 두 알고리즘 모두 예외를 throw할 수 있습니다(예: 값이 잘못된 경우 거부).

자바스크립트 코드가 기존 인덱스에 새 값을 설정하면, 먼저 인덱스 값 삭제 알고리즘이 실행되어 기존 값을 삭제하고, 그 다음 인덱스 값 설정 알고리즘이 새 값을 설정합니다.

관찰 배열 타입인 일반 속성마다 백킹 리스트가 있으며, 이는 리스트로, 초깃값은 빈 리스트입니다. 명세 저자는 백킹 리스트 내용을 수정할 수 있고, 이는 자바스크립트에서 관찰 배열 내용에도 즉시 반영됩니다. 마찬가지로 자바스크립트 코드가 관찰 배열을 수정하면 인덱스 값 설정, 인덱스 값 삭제 알고리즘을 거쳐 백킹 리스트에도 반영됩니다.

IDL에서는 관찰 배열 상수 값을 표현할 방법이 없습니다.

다음 IDL 프래그먼트는 관찰 배열 속성이 있는 인터페이스를 정의합니다:
[Exposed=Window]
interface Building {
  attribute ObservableArray<Employee> employees;
};

이 속성의 동작 정의 예시:

Building의 employees 속성에 대해 인덱스 값 설정 알고리즘(인자: employee, index):
  1. employee가 오늘 건물 출입 불가이면 "NotAllowedError" DOMException을 throw.

  2. index가 200 이상이면 QuotaExceededError를 throw하고, quota는 200, requested는 index로 설정.

  3. employee를 업무에 투입!

Building의 employees 속성에 대해 인덱스 값 삭제 알고리즘(인자: employee, index):

  1. employee가 건물을 떠났음을 경비에 알림.

자바스크립트 코드에서 employees 프로퍼티를 아래와 같이 조작할 수 있습니다:

// Building 인스턴스 얻기
const building = getBuilding();

building.employees.push(new Employee("A"));
building.employees.push(new Employee("B"));
building.employees.push(new Employee("C"));

building.employees.splice(2, 1);
const employeeB = building.employees.pop();

building.employees = [new Employee("D"), employeeB, new Employee("C")];

building.employees.length = 0;

// 예외 발생:
building.employees.push("not an Employee; a string instead");

위 조작들은 모두 인덱스 값 설정 알고리즘을 거치며, 조건에 맞으면 예외가 throw될 수 있습니다. 또한 해당 사이드 이펙트는 인덱스 값 삭제 알고리즘에서 정의된 대로 실행됩니다.

위 JS 예시에서 %Array.prototype%의 모든 자바스크립트 배열 메서드가 관찰 배열에 모두 동작하는 점도 주목하세요. 실제로 Array 인스턴스처럼 동작합니다:

const normalArray = [];

// 만약 building.employees가 인덱스 프로퍼티 getter 인터페이스였다면: normalArray에 building.employees 하나만 들어감.
//
// 관찰 배열(및 불변 배열)의 경우: normalArray에는 building.employees의 모든 항목이 들어감.
normalArray.concat(building.employees);

// names는 JS Array임.
const names = building.employees.map(employee => employee.name);

// 브랜드 체크 통과:
console.assert(building.employees instanceof Array);
console.assert(Array.isArray(building.employees));
console.assert(building.employees.constructor === Array);

// JSON.stringify에도 배열로 취급됨! (바깥 [] 참조.)
console.assert(JSON.stringify(building.employees) === `[{}]`);

2.14. 확장 속성

확장 속성은 주석이며 다음에 나타날 수 있습니다. 정의, 주석이 지정된 타입으로서의 타입, 인터페이스 멤버, 인터페이스 믹스인 멤버, 콜백 인터페이스 멤버, 네임스페이스 멤버, 딕셔너리 멤버, 그리고 연산 인수에 나타날 수 있으며, 언어 바인딩이 이러한 구문을 처리하는 방식을 제어하는 데 사용됩니다. 확장 속성은 ExtendedAttributeList로 지정되며, 이는 대괄호로 둘러싸인 쉼표로 구분된 ExtendedAttribute 목록입니다.

ExtendedAttribute 문법 기호는 거의 모든 토큰 시퀀스와 일치하지만, 이 문서에 정의된 확장 속성은 더 제한된 구문만 허용합니다. IDL 조각에서 발견되는 모든 확장 속성은 다음 문법 기호와 대조하여 어떤 형식(또는 형식들)에 해당하는지 결정합니다:

문법 기호 형식 예
ExtendedAttributeNoArgs 인수를 받지 않음 [Replaceable]
ExtendedAttributeArgList 인수 목록을 받음 현재는 사용되지 않음; 이전에는 [Constructor(double x, double y)]에서 사용됨
ExtendedAttributeNamedArgList 명명된 인수 목록을 받음 [LegacyFactoryFunction=Image(DOMString src)]
ExtendedAttributeIdent 식별자를 받음 [PutForwards=name]
ExtendedAttributeString 문자열을 받음 [Reflect="popover"]
ExtendedAttributeInteger 정수를 받음 [ReflectDefault=2]
ExtendedAttributeDecimal 십진수를 받음 [ReflectDefault=2.0]
ExtendedAttributeIntegerList 정수 목록을 받음 [ReflectRange=(2, 600)]
ExtendedAttributeIdentList 식별자 목록을 받음 [Exposed=(Window,Worker)]
ExtendedAttributeWildcard 와일드카드를 받음 [Exposed=*]

이 명세는 JavaScript 언어 바인딩에 적용 가능한 여러 확장 속성을 정의하며, 이에 대해서는 § 3.3 확장 속성에서 설명합니다. 각 확장 속성 정의는 위의 다섯 가지 형식 중 어떤 형식이 허용되는지 명시합니다.

ExtendedAttributeList ::
    [ ExtendedAttribute ExtendedAttributes ]
    ε
ExtendedAttributes ::
    , ExtendedAttribute ExtendedAttributes
    ε
ExtendedAttribute ::
    ( ExtendedAttributeInner ) ExtendedAttributeRest
    [ ExtendedAttributeInner ] ExtendedAttributeRest
    { ExtendedAttributeInner } ExtendedAttributeRest
    Other ExtendedAttributeRest
ExtendedAttributeRest ::
    ExtendedAttribute
    ε
ExtendedAttributeInner ::
    ( ExtendedAttributeInner ) ExtendedAttributeInner
    [ ExtendedAttributeInner ] ExtendedAttributeInner
    { ExtendedAttributeInner } ExtendedAttributeInner
    OtherOrComma ExtendedAttributeInner
    ε
Other ::
    integer
    decimal
    identifier
    string
    other
    -
    -Infinity
    .
    ...
    :
    ;
    <
    =
    >
    ?
    *
    ByteString
    DOMString
    FrozenArray
    Infinity
    NaN
    ObservableArray
    Promise
    USVString
    any
    bigint
    boolean
    byte
    double
    false
    float
    long
    null
    object
    octet
    or
    optional
    record
    sequence
    short
    symbol
    true
    unsigned
    undefined
    ArgumentNameKeyword
    BufferRelatedType
OtherOrComma ::
    Other
    ,
IdentifierList ::
    identifier Identifiers
Identifiers ::
    , identifier Identifiers
    ε
IntegerList ::
    integer Integers
Integers ::
    , integer Integers
    ε
ExtendedAttributeNoArgs ::
    identifier
ExtendedAttributeArgList ::
    identifier ( ArgumentList )
ExtendedAttributeIdent ::
    identifier = identifier
ExtendedAttributeString ::
    identifier = string
ExtendedAttributeInteger ::
    identifier = integer
ExtendedAttributeDecimal ::
    identifier = decimal
ExtendedAttributeWildcard ::
    identifier = *
ExtendedAttributeIdentList ::
    identifier = ( IdentifierList )
ExtendedAttributeIntegerList ::
    identifier = ( IntegerList )
ExtendedAttributeNamedArgList ::
    identifier = identifier ( ArgumentList )

3. 자바스크립트 바인딩

이 절에서는 § 2 인터페이스 정의 언어에 정의된 IDL로 작성된 정의들이 ECMAScript 언어 명세 [ECMA-262]에 규정된 자바스크립트의 특정 구조와 어떻게 대응되는지 설명한다.

별도 명시 없으면, 이 절에서 정의된 객체는 ECMAScript § 10.1 일반 객체 내부 메서드와 내부 슬롯에 기술된 일반 객체이며, 객체가 함수 객체라면 ECMAScript § 10.3 내장 함수 객체에 따른다.

이 절에서는 객체의 내부 메서드와 내부 슬롯 일부를 재정의할 수 있다. 다른 현행 표준 또한 인터페이스의 인스턴스인 플랫폼 객체의 내부 메서드나 내부 슬롯 정의를 재정의할 수 있다. 이렇게 의미가 변경된 객체는 특이 객체 규칙에 따라 다뤄져야 한다.

자바스크립트 객체의 내부 메서드를 재정의하는 것은 저수준 작업이며, 일반 객체와 다르게 동작할 수 있으므로, 보안이나 호환성 등 꼭 필요한 경우에만 써야 한다. 현재 HTMLAllCollection 및 Location 인터페이스 정의에 사용됨. [HTML]

별도 명시 없으면, 이 절 및 다른 현행 표준에서 정의된 특이 객체(Exotic Object)는 일반 객체와 동일한 내부 슬롯을 가지며, 별도 정의가 없는 모든 내부 메서드는 일반 객체의 내부 메서드와 동일하다.

별도 명시 없으면, 이 절에서 정의된 객체의 [[Extensible]] 내부 슬롯 값은 true이다.

별도 명시 없으면, 이 절에서 정의된 객체의 [[Prototype]] 내부 슬롯 값은 %Object.prototype%이다.

이 절에서 설명하는 일부 객체는 클래스 문자열을 가진다. 클래스 문자열은 Object.prototype.toString의 반환 문자열에 포함되는 값이다.

객체가 클래스 문자열 classString을 가지면, 생성 시점에 해당 객체는 %Symbol.toStringTag% 심볼 이름의 프로퍼티를 가져야 하며, PropertyDescriptor{[[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true, [[Value]]: classString}로 설정한다.

이 절의 알고리즘은 ECMAScript § 5.2 알고리즘 규칙(단계와 하위 단계, 수학 연산 등) 및 ECMA-262의 다른 부분에서 정의된 추상 연산·표기법을 따른다.

알고리즘에서 throw SomethingError 라고 하면, 이는 현재 realm에서 새로운 자바스크립트 SomethingError 객체를 생성해 throw하는 것을 의미하며, ECMA-262 알고리즘과 동일하다.

알고리즘 단계에서 다른 알고리즘이나 추상 연산을 호출하고, 그 과정에서 예외가 명시적으로 처리되지 않는 경우, 예외가 발생하면 알고리즘 실행은 중단되고 예외가 호출자에게 전달된다.

다음 알고리즘을 보자:

  1. x를 이 알고리즘에 전달된 자바스크립트 값으로 둔다.

  2. y를 ? ToString(x) 호출 결과로 둔다.

  3. y를 반환한다.

ToString은 예외를 throw할 수 있다(예: ({ toString: function() { throw 1 } }) 전달 시). 위 알고리즘에서 예외가 처리되지 않으므로, 예외가 발생하면 알고리즘 실행은 중단되고 예외가 호출자에게 전달된다.

3.1. 자바스크립트 환경

주어진 IDL 프래그먼트 집합의 자바스크립트 구현에서는, 해당 IDL 프래그먼트에 정의된 객체에 대응되는 여러 자바스크립트 객체가 존재한다. 이 객체들을 초기 객체라 하며, 다음을 포함한다:

각 realm에는 고유한 초기 객체 집합이 있어야 하며, 해당 realm의 자바스크립트 실행 컨텍스트 진입 전, realm의 글로벌 객체가 생성된 후에 만들어진다. 동일 realm의 모든 초기 객체 [[Prototype]]은 그 realm에서 가져와야 한다.

HTML 사용자 에이전트에서는 여러 realm이 프레임 또는 윈도우가 여러 개일 때 존재할 수 있다. 각 프레임·윈도우마다 고유한 초기 객체 집합을 가지며, 아래 HTML 문서로 확인할 수 있다:

<!DOCTYPE html>
<title>Different Realms</title>
<iframe id=a></iframe>
<script>
var iframe = document.getElementById("a");
var w = iframe.contentWindow;              // 프레임의 글로벌 객체

Object == w.Object;                        // false 반환 (ECMA-262 준수)
Node == w.Node;                            // false 반환
iframe instanceof w.Node;                  // false 반환
iframe instanceof w.Object;                // false 반환
iframe.appendChild instanceof Function;    // true 반환
iframe.appendChild instanceof w.Function;  // false 반환
</script>

참고: 모든 인터페이스는 어떤 realm에 노출되는지 정의한다. 예를 들어, Web Worker용 realm은 웹 페이지 realm과 노출되는 인터페이스 집합이 다를 수 있다.

작성 시점에서 자바스크립트 명세에는 반영되지 않았으나, 모든 자바스크립트 객체는 연결된 realm을 가져야 한다. 객체와 realm을 연결하는 메커니즘은 아직 명확히 규정되지 않았으나, 플랫폼 객체의 경우 연결된 realm은 객체의 관련 realm과 동일하며, 특이하지 않은 함수 객체(즉, 호출 가능 프록시나 bound 함수가 아닌 경우)는 함수 객체의 [[Realm]] 내부 슬롯의 값이 연결된 realm이다.

3.2. 자바스크립트 타입 매핑

이 절에서는 IDL의 타입이 자바스크립트 타입에 어떻게 매핑되는지 설명한다.

아래 각 하위 절에서는 특정 IDL 타입 값이 자바스크립트에서 어떻게 표현되는지 설명한다. 각 IDL 타입마다, 자바스크립트 값이 해당 타입을 기대하는 플랫폼 객체에 전달될 때 어떻게 IDL 값으로 변환되는지와, 해당 타입의 IDL 값이 플랫폼 객체에서 반환될 때 어떻게 자바스크립트 값으로 변환되는지를 설명한다.

아래 하위 절과 알고리즘은, 타입 헤더에 명시된 타입에 확장 속성을 적용해 만든 주석 타입에도 동일하게 적용된다.

3.2.1. any

IDL any 타입은 모든 다른 IDL 타입의 합집합이므로, 모든 자바스크립트 값 타입에 대응될 수 있다.

자바스크립트 값 V를 IDL 값으로 변환해 IDL any 값으로 만드는 알고리즘:

  1. V가 undefined이면, 고유한 undefined IDL 값을 반환한다.

  2. V가 null이면, null object? 참조를 반환한다.

  3. V가 불리언이면, 동일한 진릿값을 나타내는 boolean 값을 반환한다.

  4. V가 숫자이면, V를 unrestricted double로 변환한 결과를 반환한다.

  5. V가 BigInt이면, V를 bigint로 변환한 결과를 반환한다.

  6. V가 문자열이면, V를 DOMString으로 변환한 결과를 반환한다.

  7. V가 심볼이면, V를 symbol로 변환한 결과를 반환한다.

  8. V가 객체이면, V를 참조하는 IDL object 값을 반환한다.

IDL any 값은 자바스크립트 값으로 변환될 때, 해당 IDL any 값의 특정 타입에 대해 아래 절에서 설명한 변환 규칙을 따른다.

3.2.2. undefined

자바스크립트 값 V를 IDL 값으로 변환해 undefined 값으로 만들 때는, V를 무시하고 고유한 undefined 값을 반환한다.

고유한 IDL undefined 값은 자바스크립트 값으로 변환될 때 자바스크립트 undefined 값이 된다.

3.2.3. boolean

자바스크립트 값 V를 IDL 값으로 변환해 boolean 값으로 만드는 알고리즘:

  1. x를 ToBoolean(V) 결과로 둔다.

  2. 자바스크립트 불리언 값 x와 동일한 진릿값을 나타내는 IDL boolean 값을 반환한다.

IDL boolean 값 true는 자바스크립트 값으로 변환될 때 자바스크립트 true 값이 되고, IDL boolean 값 false 는 자바스크립트 false 값이 된다.

3.2.4. 정수 타입

이 절에서 사용하는 수학 연산은, ECMAScript § 5.2 알고리즘 규칙에 정의된 것 포함, 수학적 실수에 대한 정확한 수학적 결과를 의미한다.

즉, x가 Number 값일 때, “x에 대해 연산한다”는 것은 “x와 동일한 수치 값을 가진 수학적 실수에 대해 연산한다”의 약어이다.

3.2.4.1. byte

자바스크립트 값 V를 IDL 값으로 변환해 byte 값으로 만드는 알고리즘:

  1. x를 ? ConvertToInt(V, 8, "signed") 결과로 둔다.

  2. x와 동일한 수치 값을 나타내는 IDL byte 값을 반환한다.

IDL byte 값을 자바스크립트 값으로 변환한 결과는, 해당 IDL byte 값과 동일한 수치 값을 가진 Number이다. Number 값은 [−128, 127] 범위의 정수다.

3.2.4.2. octet

자바스크립트 값 V를 IDL 값으로 변환해 octet 값으로 만드는 알고리즘:

  1. x를 ? ConvertToInt(V, 8, "unsigned") 결과로 둔다.

  2. x와 동일한 수치 값을 나타내는 IDL octet 값을 반환한다.

IDL octet 값을 자바스크립트 값으로 변환한 결과는, 해당 IDL octet 값과 동일한 수치 값을 가진 Number이다. Number 값은 [0, 255] 범위의 정수다.

3.2.4.3. short

자바스크립트 값 V를 IDL 값으로 변환해 short 값으로 만드는 알고리즘:

  1. x를 ? ConvertToInt(V, 16, "signed") 결과로 둔다.

  2. x와 동일한 수치 값을 나타내는 IDL short 값을 반환한다.

IDL short 값을 자바스크립트 값으로 변환한 결과는, 해당 IDL short 값과 동일한 수치 값을 가진 Number이다. Number 값은 [−32768, 32767] 범위의 정수다.

3.2.4.4. unsigned short

자바스크립트 값 V를 IDL 값으로 변환해 unsigned short 값으로 만드는 알고리즘:

  1. x를 ? ConvertToInt(V, 16, "unsigned") 결과로 둔다.

  2. x와 동일한 수치 값을 나타내는 IDL unsigned short 값을 반환한다.

IDL unsigned short 값을 자바스크립트 값으로 변환한 결과는, 해당 IDL unsigned short 값과 동일한 수치 값을 가진 Number이다. Number 값은 [0, 65535] 범위의 정수다.

3.2.4.5. long

자바스크립트 값 V를 IDL 값으로 변환해 long 값으로 만드는 알고리즘:

  1. x를 ? ConvertToInt(V, 32, "signed") 결과로 둔다.

  2. x와 동일한 수치 값을 나타내는 IDL long 값을 반환한다.

IDL long 값을 자바스크립트 값으로 변환한 결과는, 해당 IDL long 값과 동일한 수치 값을 가진 Number이다. Number 값은 [−2147483648, 2147483647] 범위의 정수다.

3.2.4.6. unsigned long

자바스크립트 값 V를 IDL 값으로 변환해 unsigned long 값으로 만드는 알고리즘:

  1. x를 ? ConvertToInt(V, 32, "unsigned") 결과로 둔다.

  2. x와 동일한 수치 값을 나타내는 IDL unsigned long 값을 반환한다.

IDL unsigned long 값을 자바스크립트 값으로 변환한 결과는, 해당 IDL unsigned long 값과 동일한 수치 값을 가진 Number이다. Number 값은 [0, 4294967295] 범위의 정수다.

3.2.4.7. long long

자바스크립트 값 V를 IDL 값으로 변환해 long long 값으로 만드는 알고리즘:

  1. x를 ? ConvertToInt(V, 64, "signed") 결과로 둔다.

  2. x와 동일한 수치 값을 나타내는 IDL long long 값을 반환한다.

IDL long long 값을 자바스크립트 값으로 변환한 결과는, 해당 long long 값에 가장 가까운 Number 값이다. 두 값이 동일하게 가까울 경우 유효숫자가 짝수인 값을 선택한다. long long이 [−253 + 1, 253 − 1] 범위에 있으면 Number가 long long과 동일한 값을 정확히 표현할 수 있다.

3.2.4.8. unsigned long long

자바스크립트 값 V를 IDL 값으로 변환해 unsigned long long 값으로 만드는 알고리즘:

  1. x를 ? ConvertToInt(V, 64, "unsigned") 결과로 둔다.

  2. x와 동일한 수치 값을 나타내는 IDL unsigned long long 값을 반환한다.

IDL unsigned long long 값을 자바스크립트 값으로 변환한 결과는, 해당 unsigned long long 값에 가장 가까운 Number 값이다. 두 값이 동일하게 가까울 경우 유효숫자가 짝수인 값을 선택한다. unsigned long long이 253 − 1 이하이면 Number가 unsigned long long과 동일한 값을 정확히 표현할 수 있다.

3.2.4.9. 추상 연산

IntegerPart(n):

  1. r를 floor(abs(n))로 둔다.

  2. n < 0이면 -1 × r을 반환한다.

  3. 그 외에는 r을 반환한다.

ConvertToInt(V, bitLength, signedness):

  1. bitLength가 64인 경우:

    1. upperBound를 253 − 1로 둡니다.

    2. signedness가 "unsigned"이면, lowerBound를 0으로 둡니다.

    3. 그렇지 않으면 lowerBound를 −253 + 1로 둡니다.

      참고: 이렇게 하면 long long 타입이 [EnforceRange] 또는 [Clamp] 확장 속성과 연결된 경우 JavaScript의 Number 타입에서 모호하지 않은 정수로 표현할 수 있습니다.

  2. 그렇지 않고, signedness가 "unsigned"인 경우:

    1. lowerBound를 0으로 둡니다.

    2. upperBound를 2bitLength − 1로 둡니다.

  3. 그렇지 않은 경우:

    1. lowerBound를 -2bitLength − 1로 둡니다.

    2. upperBound를 2bitLength − 1 − 1로 둡니다.

  4. x를 ? ToNumber(V)로 둡니다.

  5. x가 −0이면, x를 +0으로 설정합니다.

  6. 변환 대상이 [EnforceRange] 확장 속성과 연결된 IDL 타입인 경우:

    1. x가 NaN, +∞ 또는 −∞이면, TypeError를 발생시킵니다.

    2. x를 IntegerPart(x)로 설정합니다.

    3. x < lowerBound 또는 x > upperBound이면, TypeError를 발생시킵니다.

    4. x를 반환합니다.

  7. x가 NaN이 아니고 변환 대상이 [Clamp] 확장 속성과 연결된 IDL 타입이면, 다음을 수행합니다:

    1. x를 min(max(x, lowerBound), upperBound)로 설정합니다.

    2. x를 가장 가까운 정수로 반올림하되, 두 정수의 정확히 중간에 있으면 짝수를 선택하고 두 정수 사이에서는, −0 대신 +0을 선택합니다.

    3. x를 반환합니다.

  8. x가 NaN, +0, +∞ 또는 −∞이면, +0을 반환합니다.

  9. x를 IntegerPart(x)로 설정합니다.

  10. x를 x 모듈로 2bitLength로 설정합니다.

  11. signedness가 "signed"이고 x ≥ 2bitLength − 1이면, x − 2bitLength를 반환합니다.

  12. 그렇지 않으면, x를 반환합니다.

3.2.5. float

자바스크립트 값 V를 IDL 값으로 변환해 float 값으로 만드는 알고리즘:

  1. x를 ? ToNumber(V) 결과로 둔다.

  2. x 가 NaN , +∞ 또는 −∞이면 TypeError 를 throw 한다.

  3. S를 유한 IEEE 754 단정밀도 부동소수점 값 집합(−0 제외)에 2128, −2128 두 특수값을 추가한 집합으로 둔다.

  4. y를 x에 가장 가까운 S 내 값으로 두고, 동일하게 가까울 경우 유효숫자가 짝수인 값을 선택한다. (2128, −2128도 짝수 유효숫자로 간주.)

  5. y 가 2 128 또는 −2 128 이면 TypeError 를 throw 한다.

  6. y가 +0이고 x가 음수면 −0을 반환.

  7. y를 반환.

IDL float 값을 자바스크립트 값으로 변환한 결과는, 해당 IDL float 값과 동일한 수치 값을 가진 Number이다.

3.2.6. unrestricted float

자바스크립트 값 V를 IDL 값으로 변환해 unrestricted float 값으로 만드는 알고리즘:

  1. x를 ? ToNumber(V) 결과로 둔다.

  2. x가 NaN이면 IEEE 754 NaN 값(bit 패턴 0x7fc00000)과 대응되는 IDL unrestricted float 값을 반환.

  3. S를 유한 IEEE 754 단정밀도 부동소수점 값 집합(−0 제외)에 2128, −2128 두 특수값을 추가한 집합으로 둔다.

  4. y를 x에 가장 가까운 S 내 값으로 두고, 동일하게 가까울 경우 유효숫자가 짝수인 값을 선택한다. (2128, −2128도 짝수 유효숫자로 간주.)

  5. y가 2128이면 +∞를 반환.

  6. y가 −2128이면 −∞를 반환.

  7. y가 +0이고 x가 음수면 −0을 반환.

  8. y를 반환.

참고: 자바스크립트 NaN 값이 하나뿐이므로, 단정밀도 IEEE 754 NaN 값 중 하나로 정규화해야 한다. 위에서 언급한 NaN 값(bit 패턴 0x7fc00000)은 32비트 부호 없는 정수로 해석할 때 값이 가장 작은 조용한 NaN이다.

IDL unrestricted float 값을 자바스크립트 값으로 변환한 결과는 Number:

  1. 해당 IDL unrestricted float 값이 NaN이면 Number 값도 NaN이다.

  2. 그 외에는 해당 IDL unrestricted float 값과 동일한 수치 값을 가진 Number이다.

3.2.7. double

자바스크립트 값 V를 IDL 값으로 변환해 double 값으로 만드는 알고리즘:

  1. x를 ? ToNumber(V) 결과로 둔다.

  2. x 가 NaN , +∞ 또는 −∞이면 TypeError 를 throw 한다.

  3. x와 동일한 수치 값을 나타내는 IDL double 값을 반환.

IDL double 값을 자바스크립트 값으로 변환한 결과는, 해당 double 값과 동일한 수치 값을 가진 Number이다.

3.2.8. unrestricted double

자바스크립트 값 V를 IDL 값으로 변환해 unrestricted double 값으로 만드는 알고리즘:

  1. x를 ? ToNumber(V) 결과로 둔다.

  2. x가 NaN이면 IEEE 754 NaN 값(bit 패턴 0x7ff8000000000000)과 대응되는 IDL unrestricted double 값을 반환.

  3. x와 동일한 수치 값을 나타내는 IDL unrestricted double 값을 반환.

참고: 자바스크립트 NaN 값이 하나뿐이므로, 배정밀도 IEEE 754 NaN 값 중 하나로 정규화해야 한다. 위에서 언급한 NaN 값(bit 패턴 0x7ff8000000000000)은 64비트 부호 없는 정수로 해석할 때 값이 가장 작은 조용한 NaN이다.

IDL unrestricted double 값을 자바스크립트 값으로 변환한 결과는 Number:

  1. 해당 IDL unrestricted double 값이 NaN이면 Number 값도 NaN이다.

  2. 그 외에는 해당 IDL unrestricted double 값과 동일한 수치 값을 가진 Number이다.

3.2.9. bigint

자바스크립트 값 V를 IDL 값으로 변환해 bigint 값으로 만드는 알고리즘:

  1. x를 ? ToBigInt(V) 결과로 둔다.

  2. x와 동일한 수치 값을 나타내는 IDL bigint 값을 반환.

IDL bigint 값을 자바스크립트 값으로 변환한 결과는 BigInt:

  1. 해당 IDL bigint 값과 동일한 수치 값을 가진 BigInt 값을 반환.

자바스크립트 값 V를 변환해서 IDL 숫자 타입 T 또는 bigint 값으로 만드는 알고리즘:

  1. x를 ? ToNumeric(V) 결과로 둔다.

  2. x가 BigInt면

    1. x와 동일한 수치 값을 나타내는 IDL bigint 값을 반환.

  3. 단언: x는 Number이다.

  4. x를 T로 변환한 결과를 반환.

3.2.10. DOMString

JavaScript 값 V는 다음 알고리즘을 실행하여 변환되어 IDL DOMString 값이 됩니다:

  1. V가 null이고 변환 대상이 [LegacyNullToEmptyString] 확장 속성과 연결된 IDL 타입이면, 빈 문자열을 나타내는 DOMString 값을 반환합니다.

  2. x를 ? ToString(V)로 둡니다.

  3. JavaScript String 값 x가 나타내는 것과 동일한 코드 단위 시퀀스를 나타내는 IDL DOMString 값을 반환합니다.

IDL DOMString 값을 JavaScript 값으로 변환한 결과는 IDL DOMString이 나타내는 것과 동일한 코드 단위 시퀀스를 나타내는 String 값입니다.

3.2.11. ByteString

자바스크립트 값 V를 IDL 값으로 변환해 ByteString 값으로 만드는 알고리즘:

  1. x를 ? ToString(V) 결과로 둔다.

  2. x의 어떤 요소 값이 255를 초과하면 throw TypeError.

  3. x와 길이가 같고 각 요소 값이 x의 해당 요소와 동일한 IDL ByteString 값을 반환.

IDL ByteString 값을 자바스크립트 값으로 변환한 결과는, 해당 ByteString과 길이가 같고 각 요소 값이 ByteString의 해당 요소와 동일한 String 값이다.

3.2.12. USVString

자바스크립트 값 V를 IDL 값으로 변환해 USVString 값으로 만드는 알고리즘:

  1. string을 V를 DOMString으로 변환한 결과로 둔다.

  2. string을 자바스크립트 문자열 변환을 통해 스칼라 값 시퀀스로 변환한 결과인 IDL USVString 값을 반환.

IDL USVString 값 S를 자바스크립트 값으로 변환한 결과는 S 자체다.

3.2.13. object

IDL object 값은 자바스크립트 Object 값으로 표현된다.

자바스크립트 값 V를 IDL 값으로 변환해 object 값으로 만드는 알고리즘:

  1. V가 Object가 아니면 TypeError를 던집니다.

  2. V와 동일 객체를 참조하는 IDL object 값을 반환.

IDL object 값을 자바스크립트 값으로 변환한 결과는, 해당 object가 참조하는 동일 객체를 나타내는 Object 값이다.

3.2.14. symbol

IDL symbol 값은 자바스크립트 Symbol 값으로 표현된다.

자바스크립트 값 V를 IDL 값으로 변환해 symbol 값으로 만드는 알고리즘:
  1. V가 Symbol이 아니면 TypeError를 던집니다.

  2. V와 동일 심볼을 참조하는 IDL symbol 값을 반환.

IDL symbol 값을 자바스크립트 값으로 변환한 결과는, 해당 symbol과 동일 심볼을 참조하는 Symbol 값이다.

3.2.15. 인터페이스 타입

IDL 인터페이스 타입 값은 자바스크립트 Object 값(함수 객체 포함)으로 표현된다.

자바스크립트 값 V를 IDL 값으로 변환해 인터페이스 타입 값으로 만드는 알고리즘(I는 해당 인터페이스):

  1. V가 I를 구현하면, 해당 플랫폼 객체를 참조하는 IDL 인터페이스 타입 값을 반환.

  2. throw TypeError.

IDL 인터페이스 타입 값을 자바스크립트 값으로 변환한 결과는, 해당 인터페이스 타입 값이 참조하는 동일 객체를 나타내는 Object 값이다.

3.2.16. 콜백 인터페이스 타입

IDL 콜백 인터페이스 타입 값은 자바스크립트 Object 값(함수 객체 포함)으로 표현된다.

자바스크립트 값 V를 IDL 값으로 변환해 콜백 인터페이스 타입 값으로 만드는 알고리즘:

  1. V 가 객체가 아니면 , TypeError 를 throw 한다.

  2. V를 참조하고, incumbent settings object를 콜백 컨텍스트로 하는 IDL 콜백 인터페이스 타입 값을 반환.

IDL 콜백 인터페이스 타입 값을 자바스크립트 값으로 변환한 결과는, 해당 콜백 인터페이스 타입 값이 참조하는 동일 객체를 나타내는 Object 값이다.

3.2.17. 딕셔너리 타입

IDL 딕셔너리 타입 값은 JavaScript Object 값으로 표현됩니다. 객체(또는 그 프로토타입 체인)의 속성은 딕셔너리 멤버에 대응합니다.

JavaScript 값 jsDict는 변환되어 IDL 딕셔너리 타입 값이 되며, 다음 알고리즘을 실행합니다(여기서 D는 딕셔너리 타입입니다):

  1. jsDict가 Object가 아니고 jsDict가 undefined도 null도 아니라면, TypeError를 발생시킵니다.

  2. idlDict를 타입 D의 딕셔너리를 나타내는 빈 순서가 지정된 맵으로 둡니다.

  3. dictionaries를 D와 D의 모든 상속된 딕셔너리로 구성된 목록으로 두고, 가장 덜 파생된 것부터 가장 많이 파생된 것 순서로 정렬합니다.

  4. dictionaries의 각 딕셔너리 dictionary에 대해 순서대로:

    1. dictionary에 선언된 각 딕셔너리 멤버 member에 대해 사전순으로:

      1. key를 member의 식별자로 둡니다.

      2. jsDict가 undefined 또는 null인 경우:

        1. jsMemberValue를 undefined로 둡니다.

      3. 그렇지 않으면,

        1. jsMemberValue를 ? Get(jsDict, key)로 둡니다.

      4. jsMemberValue가 undefined가 아닌 경우:

        1. idlMemberValue를 jsMemberValue를 member가 선언된 타입의 IDL 값으로 변환한 결과로 둡니다.

        2. idlDict[key]를 설정하여 idlMemberValue로 합니다.

      5. 그렇지 않고, jsMemberValue가 undefined이지만 member에 기본값이 있는 경우:

        1. idlMemberValue를 member의 기본값으로 둡니다.

        2. idlDict[key]를 설정하여 idlMemberValue로 합니다.

      6. 그렇지 않고, jsMemberValue가 undefined이고 member가 필수인 경우, TypeError를 발생시킵니다.

  5. idlDict를 반환합니다.

참고: JavaScript 객체에서 딕셔너리 멤버를 조회하는 순서는 객체의 속성 열거 순서와 반드시 같지는 않습니다.

IDL 딕셔너리 값 V는 변환되어 JavaScript Object 값이 되며, 다음 알고리즘을 실행합니다(여기서 D는 딕셔너리입니다):

  1. O를 OrdinaryObjectCreate(%Object.prototype%)로 둡니다.

  2. dictionaries를 D와 D의 모든 상속된 딕셔너리로 구성된 목록으로 두고, 가장 덜 파생된 것부터 가장 많이 파생된 것 순서로 정렬합니다.

  3. dictionaries의 각 딕셔너리 dictionary에 대해 순서대로:

    1. dictionary에 선언된 각 딕셔너리 멤버 member에 대해 사전순으로:

      1. key를 member의 식별자로 둡니다.

      2. V[key]가 존재하는 경우:

        1. idlValue를 V[key]로 둡니다.

        2. value를 idlValue를 JavaScript 값으로 변환한 결과로 둡니다.

        3. ! CreateDataPropertyOrThrow(O, key, value)를 수행합니다.

        member에 기본값이 있으면, key는 항상 V에 존재한다는 점을 기억하십시오.

  4. O를 반환합니다.

3.2.18. 열거형 타입

IDL 열거형 타입은 자바스크립트 String 값으로 표현된다.

자바스크립트 값 V를 IDL 값으로 변환해 열거형 타입 값으로 만드는 방법(E는 해당 열거형):

  1. S를 ? ToString(V) 결과로 둔다.

  2. S가 E의 열거형 값에 포함되지 않으면 throw TypeError.

  3. S와 동일한 E 타입의 열거형 값을 반환.

IDL 열거형 타입 값을 자바스크립트 값으로 변환한 결과는, 해당 열거형 값과 동일한 코드 유닛 시퀀스를 나타내는 String 값이다.

3.2.19. 콜백 함수 타입

IDL 콜백 함수 타입은 자바스크립트 함수 객체로 표현된다. 단, [LegacyTreatNonObjectAsNull]이 붙은 경우에는 아무 객체나 될 수 있다.

JavaScript 값 V는 변환되어 다음 알고리즘을 실행함으로써 IDL 콜백 함수 타입 값이 됩니다:

  1. IsCallable(V) 호출 결과가 false이고 IDL 값으로의 변환이 V가 속성에 할당되었기 때문에 수행되는 것이 아니며, 해당 속성의 타입이 널 허용 콜백 함수이고 [LegacyTreatNonObjectAsNull]로 주석이 지정되어 있다면, TypeError를 발생시킵니다.

  2. V가 나타내는 것과 동일한 객체에 대한 참조를 나타내고, 현직 설정 객체를 콜백 컨텍스트로 하는 IDL 콜백 함수 타입 값을 반환합니다.

IDL 콜백 함수 타입 값을 자바스크립트 값으로 변환한 결과는, 해당 콜백 함수 타입 값이 참조하는 동일 객체를 나타내는 값이다.

3.2.20. 널 허용 타입 — T?

IDL 널 허용 타입 값은 내부 IDL 타입에 대응하는 JavaScript 타입의 값 또는 JavaScript null 값으로 표현됩니다.

JavaScript 값 V는 변환되어 IDL 널 허용 타입 T? 값(T는 내부 타입)이 되며, 다음과 같습니다:

  1. V가 Object가 아니고, IDL 값으로의 변환이 V가 속성에 할당되었기 때문에 수행되고 그 타입이 널 허용 콜백 함수이며 [LegacyTreatNonObjectAsNull]로 주석이 지정되어 있다면, IDL 널 허용 타입 T? 값 null을 반환합니다.

  2. 그렇지 않고, V가 undefined이며, T가 undefined를 포함한다면, 유일한 undefined 값을 반환합니다.

  3. 그렇지 않고, V가 null 또는 undefined이면, IDL 널 허용 타입 T? 값 null을 반환합니다.

  4. 그렇지 않으면, V를 변환한 결과를 반환하며, 내부 IDL 타입 T에 대한 규칙을 사용합니다.

IDL 널 허용 타입 값을 JavaScript 값으로 변환한 결과는 다음과 같습니다:

  1. IDL 널 허용 타입 T? 값이 null이면, JavaScript 값은 null입니다.

  2. 그렇지 않으면, JavaScript 값은 IDL 널 허용 타입 값을 내부 IDL 타입 T으로 변환한 결과입니다.

3.2.21. 시퀀스 — sequence<T>

IDL sequence<T> 값은 자바스크립트 Array 값으로 표현된다.

자바스크립트 값 V를 IDL 값으로 변환해 sequence<T> 값으로 만드는 방법:

  1. V 가 객체가 아니면 , TypeError 를 throw 한다.

  2. method를 ? GetMethod(V, %Symbol.iterator%) 결과로 둔다.

  3. method 가 undefined 이면 TypeError 를 throw 한다.

  4. V와 method로 시퀀스 생성 결과를 반환.

sequence<T> 타입의 IDL 시퀀스 값 S를 자바스크립트 Array 객체로 변환하는 방법:

  1. n을 S의 길이로 둔다.

  2. A를 [] 식으로 생성한 새 Array 객체로 둔다.

  3. i를 0으로 초기화.

  4. i < n 동안:

    1. V를 S의 인덱스 i의 값으로 둔다.

    2. E를 V를 자바스크립트 값으로 변환한 결과로 둔다.

    3. P를 ! ToString(i) 결과로 둔다.

    4. ! CreateDataPropertyOrThrow(A, P, E)을 수행.

    5. i를 i + 1로 설정.

  5. A를 반환.

3.2.21.1. 이터러블에서 시퀀스 생성하기

이터러블 iterable과 이터레이터 getter method가 주어졌을 때, sequence<T> 타입의 IDL 값을 생성하려면 다음 단계를 수행한다:

  1. iteratorRecord를 ? GetIteratorFromMethod(iterable, method)로 설정한다.

  2. i를 0으로 초기화한다.

  3. 반복한다

    1. next를 ? IteratorStepValue(iteratorRecord)로 설정한다.

    2. next가 done이면, i 길이의 sequence<T> 타입의 IDL 시퀀스 값을 반환한다. 이때 인덱스 j의 요소 값은 Sj이다.

    3. Si를 next를 T 타입의 IDL 값으로 변환한 결과로 초기화한다.

    4. i를 i + 1로 설정한다.

다음 interface는 시퀀스 타입의 attribute와 시퀀스 타입의 인자를 갖는 operation을 정의한다.

[Exposed=Window]
interface Canvas {

  sequence<DOMString> getSupportedImageCodecs();

  undefined drawPolygon(sequence<double> coordinates);
  sequence<double> getLastDrawnPolygon();

  // ...
};

이 인터페이스의 JavaScript 구현에서, String 타입의 요소를 가진 Array 객체는 sequence<DOMString>을 나타내고, Number 타입의 요소를 가진 Array는 sequence<double>을 나타낸다. Array 객체는 실질적으로 값으로 전달된다; getSupportedImageCodecs() 함수를 호출할 때마다 새로운 Array가 반환되며, Array를 drawPolygon에 전달하더라도 호출이 끝난 후 참조가 유지되지 않는다.

// Canvas 인스턴스를 얻는다. getSupportedImageCodecs()가 "image/png"와 "image/svg+xml" 두 개의 DOMString 값을 갖는 시퀀스를 반환한다고 가정.
// 길이가 2인 Array 객체.
var canvas = getCanvas();

// 길이가 2인 Array 객체.
var supportedImageCodecs = canvas.getSupportedImageCodecs();

// "image/png"로 평가됨.
supportedImageCodecs[0];

// canvas.getSupportedImageCodecs()를 호출할 때마다 새로운 Array 객체가 반환되므로, 반환된 Array를 수정해도 다음 호출의 값에는 영향이 없다.
supportedImageCodecs[0] = "image/jpeg";

// "image/png"로 평가됨.
canvas.getSupportedImageCodecs()[0];

// 각 호출마다 새로운 Array 객체가 반환되므로, 이 비교는 false가 됨.
canvas.getSupportedImageCodecs() == canvas.getSupportedImageCodecs();

// Number의 Array...
var a = [0, 0, 100, 0, 50, 62.5];

// ...을 sequence<double>을 기대하는 플랫폼 객체에 전달할 수 있음.
canvas.drawPolygon(a);

// 각 요소는 먼저 ToNumber()를 호출하여 double로 변환됨.
// 따라서 다음 호출은 이전 호출과 동일하지만 "hi"가 drawPolygon() 반환 전에 alert됨.
a = [false, "",
     { valueOf: function() { alert("hi"); return 100; } }, 0,
     "50", new Number(62.5)];
canvas.drawPolygon(a);

// drawPolygon()에 전달된 Array를 변경해도 Canvas에는 영향을 주지 않음. 값으로 전달되기 때문.
a[4] = 20;
var b = canvas.getLastDrawnPolygon();
alert(b[4]);    // "50"이 alert됨.

3.2.22. 비동기 시퀀스 — async_sequence<T>

JavaScript 바인딩에서, IDL async sequence 값은 다음 struct의 items로 표현된다:

JavaScript 값 V는 다음과 같이 IDL async_sequence<T> 값으로 변환된다:
  1. V가 Object가 아니면, 예외를 발생시킵니다: TypeError.

  2. method를 ? GetMethod(obj, %Symbol.asyncIterator%)로 설정한다.

  3. method가 undefined일 경우:

    1. syncMethod를 ? GetMethod(obj, %Symbol.iterator%)로 설정한다.

    2. syncMethod가 undefined이면, 예외를 발생시킵니다: TypeError.

    3. IDL async sequence 값을 반환한다. object는 V, method는 syncMethod, type은 "sync"로 설정된다.

  4. IDL async sequence 값을 반환한다. object는 V, method는 method, type 은 "async"로 설정된다.

IDL async_sequence<T> 값 V는 다음과 같이 JavaScript 객체로 변환됩니다:
  1. V의 object를 반환한다.

3.2.22.1. 비동기 시퀀스 반복

비동기 시퀀스는 직접적으로 반복되지 않는다. 대신 먼저 열어서 비동기 이터레이터를 생성한다. 비동기 이터레이터는 비동기적으로 반복하여 값을 생성할 수 있다.

비동기 이터레이터들은 구조체이며, 다음 항목들을 가진다:

비동기 시퀀스 열기를 위해 async_sequence<T> sequence에 대해:

  1. iterator를 ? GetIteratorFromMethod(sequence의 object, sequence의 method)로 설정한다.

  2. sequence의 type이 "sync"이면, iterator를 CreateAsyncFromSyncIterator(iterator)로 설정한다.

  3. 비동기 이터레이터 값을 반환하는데, underlying record는 iterator로, type parameter는 T로 설정한다.

비동기 이터레이터의 다음 값 구하기를 위해 비동기 이터레이터 iterator에 대해:

  1. nextResult를 IteratorNext(iterator의 underlying record)로 설정한다.

  2. nextResult가 abrupt completion이면, 거부된 프라미스(사유: nextResult.[[Value]])를 반환한다.

  3. nextPromise를 해결된 프라미스(해결값: nextResult.[[Value]])로 설정한다.

  4. nextPromise에 대해 반응한 결과를 반환하는데, 이때 iterResult를 인자로 한다:

    1. iterResult가 객체가 아니면, throw 한다. TypeError.

    2. done을 ? IteratorComplete(iterResult)로 설정한다.

    3. done이 true이면:

      1. 반복 종료를 반환한다.

    4. 그 외의 경우:

      1. V를 ? IteratorValue(iterResult)로 설정한다.

      2. value를 변환 V를 iterator의 type parameter 타입의 IDL 값으로 변환한 결과로 설정한다.

      3. value를 반환한다.

비동기 이터레이터 닫기를 위해 async iterator<T> iterator, ECMAScript 값 reason과 함께:

  1. iteratorRecord를 iterator의 underlying record로 설정한다.

  2. iteratorObj를 iteratorRecord.[[Iterator]]로 설정한다.

  3. returnMethod를 GetMethod(iteratorObj, "return")로 설정한다.

  4. returnMethod가 abrupt completion이면, 거부된 프라미스(사유: returnMethod.[[Value]])를 반환한다.

  5. returnMethod가 undefined이면, 해결된 프라미스(해결값: undefined)를 반환한다.

  6. returnResult를 Call(returnMethod.[[Value]], iteratorObj, « reason »)로 설정한다.

  7. returnResult가 abrupt completion이면, 거부된 프라미스(사유: returnResult.[[Value]])를 반환한다.

  8. returnPromise를 해결된 프라미스(해결값: returnResult.[[Value]])로 설정한다.

  9. returnPromise에 대해 반응한 결과를 반환하는데, returnPromiseResult를 인자로 한다:

    1. returnPromiseResult가 객체가 아니면, throw 한다. TypeError.

    2. undefined를 반환한다.

concatN은 operation이며, 비동기 시퀀스에서 생성된 모든 문자열을 연결한 값을 프라미스로 반환한다. 이 연결은 비동기 시퀀스가 maxN개의 문자열을 생성하면 중단되고 이터레이터를 닫는다.

interface I {
  Promise<DOMString> concatN(async_sequence<DOMString> strings, unsigned long maxN);
};

concatN(sequence, maxN) 메서드 단계:

  1. promise를 새로운 프라미스로 설정한다.

  2. result를 빈 문자열로 설정한다.

  3. n을 0으로 설정한다.

  4. iterator를 비동기 시퀀스 열기의 결과로 sequence에 대해 생성한다.

  5. step을 비동기 시퀀스를 처리할 단계들의 시퀀스로 설정한다:

    1. next를 비동기 이터레이터의 다음 값 구하기의 결과로 iterator에 대해 얻는다.

    2. 반응하여 next를 처리한다:

      • next가 값 v로 이행되었다면:

        1. v가 반복 종료라면, resolve하여 promise를 result로 이행한다.

        2. result를 result와 v를 연결한 값으로 설정한다.

        3. n을 n + 1로 설정한다.

        4. n이 maxN라면:

          1. finish를 비동기 이터레이터 닫기 결과로 iterator와 reason undefined로 얻는다.

          2. 반응하여 finish를 처리한다:

            • finish가 이행되었다면, resolve하여 promise를 result로 이행한다.

            • finish가 r로 거부되었다면, reject하여 promise를 r로 거부한다.

        5. 그 외의 경우:

          1. step을 호출한다.

      • next가 r로 거부되었다면, reject하여 promise를 r로 거부한다.

  6. step을 호출한다.

  7. promise를 반환한다.

3.2.23. 레코드 — record<K, V>

IDL record<K, V> 값은 자바스크립트 객체 값으로 표현됩니다.

자바스크립트 값 O는 변환되어 IDL record<K, V> 값으로 처리됩니다. 다음과 같은 절차를 따릅니다:

  1. O가 객체가 아니면, throw를 발생시킵니다. TypeError.

  2. result를 record<K, V> 의 새로운 빈 인스턴스로 설정합니다.

  3. keys를 ? O.[[OwnPropertyKeys]]()로 설정합니다.

  4. 각 keys의 key에 대해:

    1. desc를 ? O.[[GetOwnProperty]](key)로 설정합니다.

    2. desc가 undefined가 아니고, desc.[[Enumerable]]가 true일 경우:

      1. typedKey를 key IDL 값으로 변환 하여 타입 K로 처리합니다.

      2. value를 ? Get(O, key)의 결과로 설정합니다.

      3. typedValue를 value IDL 값으로 변환 하여 타입 V로 처리합니다.

      4. result[typedKey]에 typedValue를 설정합니다.

        참고: K가 USVString 이고 key에 짝이 없는 대리문자가 포함된 경우, typedKey가 이미 result에 있을 수 있습니다.

  5. result를 반환합니다.

IDL record<…> 값 D는 변환되어 자바스크립트 값으로 다음과 같이 처리됩니다:

  1. result를 OrdinaryObjectCreate(%Object.prototype%)의 결과로 설정합니다.

  2. 각 D의 key → value 쌍에 대해:

    1. jsKey를 key 자바스크립트 값으로 변환합니다.

    2. jsValue를 value 자바스크립트 값으로 변환합니다.

    3. created를 ! CreateDataProperty(result, jsKey, jsValue)의 결과로 설정합니다.

    4. Assert: created는 true입니다.

  3. result를 반환합니다.

자바스크립트 값 {b: 3, a: 4}를 record<DOMString, double> 인자로 전달하면, IDL 값 «[ "b" → 3, "a" → 4 ]»가 됩니다.

레코드는 자신의 열거 가능한 프로퍼티만 고려하므로, 다음과 같은 IDL 연산 record<DOMString, double> identity(record<DOMString, double> arg)이 인자를 반환할 때, 아래 코드는 assertion을 만족합니다:

let proto = {a: 3, b: 4};
let obj = {__proto__: proto, d: 5, c: 6}
Object.defineProperty(obj, "e", {value: 7, enumerable: false});
let result = identity(obj);
console.assert(result.a === undefined);
console.assert(result.b === undefined);
console.assert(result.e === undefined);
let entries = Object.entries(result);
console.assert(entries[0][0] === "d");
console.assert(entries[0][1] === 5);
console.assert(entries[1][0] === "c");
console.assert(entries[1][1] === 6);

레코드의 키와 값은 제약될 수 있으며, 키는 세 문자열 타입 중에서만 제약될 수 있습니다. 아래 변환은 다음과 같은 결과를 가집니다:

값 타입에 전달 결과
{"😞": 1} record<ByteString, double> TypeError
{"\uD83D": 1} record<USVString, double> «[ "\uFFFD" → 1 ]»
{"\uD83D": {hello: "world"}} record<DOMString, double> «[ "\uD83D" → 0 ]»

3.2.24. Promise 타입 — Promise<T>

IDL promise 타입 값은 JavaScript PromiseCapability 레코드로 표현됩니다.

JavaScript 값 V는 변환되어 IDL의 Promise<T> 값으로 처리됩니다. 절차는 다음과 같습니다:

  1. promiseCapability를 ? NewPromiseCapability(%Promise%)로 설정합니다.

  2. ? Call(promiseCapability.[[Resolve]], undefined, « V »)를 수행합니다.

  3. promiseCapability를 반환합니다.

IDL promise 타입 값을 자바스크립트 값으로 변환한 결과는, 해당 IDL promise 타입이 표현하는 레코드의 [[Promise]] 필드의 값입니다.

JS 값을 Promise<T> IDL 값으로 변환할 때, 먼저 그 값이 (IDL) Promise로 감싸지고, 이후의 메커니즘이 그 promise가 올바르게 T 타입의 값으로 해결되도록 보장합니다.

즉, 예를 들어, Promise<T> 인자를 받도록 정의된 메서드는 Promise 객체 (결국 T 객체로 해결되어야 하는)와 T 객체 자체 모두를 자동으로 허용합니다.

(처음에는 그 외의 어떤 타입의 객체도 받아들이지만, 잘못된 타입으로 해결될 경우 promise를 자동으로 거절하게 됩니다.)

3.2.24.1. Promise 생성 및 조작

새로운 promise 생성을 Promise<T> 타입으로 realm realm에서 생성하려면, 다음 단계를 수행합니다:

  1. constructor를 realm.[[Intrinsics]].[[%Promise%]]로 설정합니다.

  2. ? NewPromiseCapability(constructor)를 반환합니다.

해결된 promise 생성을 Promise<T> 타입으로 x (타입 T의 값)와 함께 realm realm에서 생성하려면, 다음 단계를 수행합니다:

  1. value를 자바스크립트 값으로 변환한 x의 결과로 설정합니다.

  2. constructor를 realm.[[Intrinsics]].[[%Promise%]]로 설정합니다.

  3. promiseCapability를 ? NewPromiseCapability(constructor)로 설정합니다.

  4. ! Call(promiseCapability.[[Resolve]], undefined, « value »)를 수행합니다.

  5. promiseCapability를 반환합니다.

거부된 promise 생성을 Promise<T> 타입으로 reason r (자바스크립트 값)과 함께 realm realm에서 생성하려면, 다음 단계를 수행합니다:

  1. constructor를 realm.[[Intrinsics]].[[%Promise%]]로 설정합니다.

  2. promiseCapability를 ? NewPromiseCapability(constructor)로 설정합니다.

  3. ! Call(promiseCapability.[[Reject]], undefined, « r »)를 수행합니다.

  4. promiseCapability를 반환합니다.

resolve를 Promise<T> p에 x (타입 T의 값)로 하려면, 다음 단계를 수행합니다:

  1. x가 주어지지 않았다면, undefined 값으로 설정합니다.

  2. value를 자바스크립트 값으로 변환한 x의 결과로 설정합니다.

  3. ! Call(p.[[Resolve]], undefined, « value »)를 수행합니다.

T가 undefined 인 경우, x 인자는 생략할 수 있으므로 더 간단한 "resolve p" 사용이 가능합니다.

reject를 Promise<T> p에 reason r (자바스크립트 값)으로 하려면, 다음 단계를 수행합니다:

  1. ! Call(p.[[Reject]], undefined, « r »)를 수행합니다.

react를 Promise<T> promise에 대해, promise가 이행되거나 거부되었을 때 수행할 1~2개의 단계 집합을 받아, 다음 단계를 수행합니다:

  1. onFulfilledSteps를 다음 단계로 설정합니다. 인자로 V를 받습니다:

    1. value를 IDL 값으로 변환한 V (타입 T)로 설정합니다.

    2. promise가 이행되었을 때 실행할 단계가 있다면, result를 해당 단계를 수행한 결과로 설정합니다. T가 undefined가 아니면 value를 인자로 전달합니다. 그렇지 않으면 result를 value로 설정합니다.

    3. result를 자바스크립트 값으로 변환하여 반환합니다.

  2. onFulfilled를 CreateBuiltinFunction(onFulfilledSteps, 1, "", « »)로 설정합니다:

  3. onRejectedSteps를 다음 단계로 설정합니다. 인자로 R를 받습니다:

    1. reason를 IDL 값으로 변환한 R (타입 any)로 설정합니다.

    2. promise가 거부되었을 때 실행할 단계가 있다면, result를 해당 단계를 수행한 결과로 설정합니다. 그렇지 않으면 result를 거부된 promise 생성 reason으로 설정합니다.

    3. result를 자바스크립트 값으로 변환하여 반환합니다.

  4. onRejected를 CreateBuiltinFunction(onRejectedSteps, 1, "", « »)로 설정합니다:

  5. constructor를 promise.[[Promise]].[[Realm]].[[Intrinsics]].[[%Promise%]]로 설정합니다.

  6. newCapability를 ? NewPromiseCapability(constructor)로 설정합니다.

    참고: 모든 호출자가 반환된 Promise를 사용할 필요는 없습니다. 구현체는 newCapability 생성 생략을 고려할 수 있습니다.

  7. PerformPromiseThen(promise.[[Promise]], onFulfilled, onRejected, newCapability)를 수행합니다.

  8. newCapability를 반환합니다.

참고: 이 알고리즘은 promise.then() 메서드와 매우 유사하게 동작합니다. 특히, 단계에서 U 타입이나 Promise<U> 값을 반환하는 경우, 이 알고리즘 역시 Promise<U> 를 반환합니다.

어떤 단계 이행 시 수행를 Promise<T> promise가 이행될 때, 타입 T 값을 받는 단계 steps로 다음을 수행합니다:

  1. react를 promise에 대해 호출한 결과를 반환합니다:

    • promise가 값 v로 이행되었다면:

      1. steps를 v로 수행합니다.

어떤 단계 거부 시 수행를 Promise<T> promise가 거부될 때, 자바스크립트 값을 받는 단계 steps로 다음을 수행합니다:

  1. react를 promise에 대해 호출한 결과를 반환합니다:

    • promise가 reason r로 거부되었다면:

      1. steps를 r로 수행합니다.

모두 대기(wait for all)를 list 타입인 Promise<T> 값 promises에 대해, list 타입 T 값을 받는 성공 단계 successSteps와 거부 reason any 값을 받는 실패 단계 failureSteps로 다음을 수행합니다:

  1. fullfilledCount를 0으로 설정합니다.

  2. rejected를 false로 설정합니다.

  3. rejectionHandlerSteps를 다음 단계로 설정합니다. 인자로 arg를 받습니다:

    1. rejected가 true이면 이 단계들을 중단합니다.

    2. rejected를 true로 설정합니다.

    3. failureSteps를 arg로 수행합니다.

  4. rejectionHandler를 CreateBuiltinFunction(rejectionHandlerSteps, 1, "", « »)로 설정합니다:

  5. total을 promises의 size로 설정합니다.

  6. total이 0이면:

    1. 마이크로태스크 큐에 successSteps를 « »로 수행하도록 추가합니다.

    2. 반환합니다.

  7. index를 0으로 설정합니다.

  8. result를 list 타입으로, total 개의 null 값으로 초기화합니다.

  9. 각 promises의 promise에 대해:

    1. promiseIndex를 index로 설정합니다.

    2. fulfillmentHandler를 다음 단계로 설정합니다. 인자로 arg를 받습니다:

      1. result[promiseIndex]에 arg를 설정합니다.

      2. fullfilledCount를 fullfilledCount+1로 설정합니다.

      3. fullfilledCount가 total과 같으면, successSteps를 result로 수행합니다.

    3. fulfillmentHandler를 CreateBuiltinFunction(fulfillmentHandler, 1, "", « »)로 설정합니다:

    4. PerformPromiseThen(promise, fulfillmentHandler, rejectionHandler)를 수행합니다.

    5. index를 index+1로 설정합니다.

모두 기다리는 promise 얻기를 list 타입 Promise<T> 값 promises와 realm realm에 대해 얻으려면, 다음 단계를 수행합니다:

  1. promise를 새로운 promise 생성으로 Promise<sequence<T>> 타입으로 realm에서 생성합니다.

  2. successSteps를 다음 단계로 설정합니다. 인자로 results를 받습니다:

    1. resolve promise를 results로 수행합니다.

  3. failureSteps를 다음 단계로 설정합니다. 인자로 reason을 받습니다:

    1. reject promise 를 reason으로 수행합니다.

  4. 모두 대기(wait for all)를 promises와 successSteps, failureSteps로 수행합니다.

  5. promise를 반환합니다.

이 정의는 여러 promise의 결과를 집계한 뒤, 그 결과로 또 다른 promise를 생성하고 싶을 때 유용합니다. JavaScript의 Promise.all() 과 같은 방식입니다. 또 다른 promise를 생성할 필요가 없다면 모두 대기(waiting for all)가 더 적합할 수 있습니다.

handled로 표시하려면 Promise<T> promise의 promise.[[Promise]].[[PromiseIsHandled]]를 true로 설정합니다.

이 정의는 거부가 자주 무시될 것으로 예상되는 promise에 유용하며, 이러한 promise가 unhandledrejection 이벤트를 발생시키지 않게 합니다. 가장 흔한 사용 사례는 웹 개발자가 확인할 수도, 하지 않을 수도 있는 promise 속성입니다. 예를 들어 writableStreamWriter.closed promise가 있습니다.

3.2.24.2. 예시

delay는 연산이며, 지정한 밀리초 후에 이행되는 promise를 반환합니다. 한 줄의 설명으로 promise를 어떻게 간단하게 resolve할 수 있는지 보여줍니다.

interface I {
  Promise<undefined> delay(unrestricted double ms);
};

delay(ms) 메서드 단계:

  1. realm을 this의 관련 렐름으로 설정한다.

  2. taskSource를 적절한 태스크 소스로 설정한다.

  3. ms가 NaN이면 ms를 +0으로, 아니면 ms와 +0 중 더 큰 값으로 ms를 설정한다.

  4. p를 새로운 promise로 realm에서 생성한다.

  5. 다음 단계를 병렬로 실행한다:

    1. ms 밀리초 대기한다.

    2. 태스크 큐에 등록하여 taskSource에 resolve p를 수행한다.

  6. p를 반환한다.

validatedDelay 연산은 delay 함수와 유사하지만, 인자를 검증합니다. 이 예시는 비동기 작업을 시작하기 전에 즉시 실패를 알릴 때 rejected promise를 어떻게 사용하는지 보여줍니다.

interface I {
  Promise<undefined> validatedDelay(unrestricted double ms);
};

validatedDelay(ms) 메서드 단계:

  1. realm을 this의 관련 렐름으로 설정한다.

  2. taskSource를 적절한 태스크 소스로 설정한다.

  3. ms가 NaN이면 거부된 promise TypeError 를 realm에서 반환한다.

  4. ms < 0이면 거부된 promise RangeError 를 realm에서 반환한다.

  5. p를 새로운 promise로 realm에서 생성한다.

  6. 다음 단계를 병렬로 실행한다:

    1. ms 밀리초 대기한다.

    2. 태스크 큐에 등록하여 taskSource에 resolve p를 수행한다.

  7. p를 반환한다.

addDelay는 연산이며, promise가 settle된 후 반환 promise가 settle되기까지 추가 밀리초 지연을 제공합니다.

interface I {
  Promise<any> addDelay(Promise<any> promise, unrestricted double ms);
};

addDelay(ms, promise) 메서드 단계:

  1. realm을 this의 관련 렐름으로 설정한다.

  2. taskSource를 적절한 태스크 소스로 설정한다.

  3. ms가 NaN이면 ms를 +0으로, 아니면 ms와 +0 중 더 큰 값으로 ms를 설정한다.

  4. p를 새로운 promise로 realm에서 생성한다.

  5. React를 promise에 대해 수행한다:

  6. p를 반환한다.

environment.ready는 특성(attribute)이며, 환경(예: DOM 문서)의 일부가 "준비됨" 상태가 되었음을 알립니다. 환경 비동기성을 표현하는 방법을 보여줍니다.

interface Environment {
  readonly attribute Promise<undefined> ready;
};

모든 Environment 객체는 ready promise를 가져야 하며, 이 값은 Promise<undefined>이다.

ready 특성 getter 단계:

  1. this의 ready promise를 반환한다.

Environment 객체를 realm realm에서 생성하려면, 다음 단계를 수행합니다:

  1. taskSource를 적절한 태스크 소스로 설정한다.

  2. environment를 새로운 Environment 객체로 realm에서 생성한다.

  3. environment의 ready promise를 새로운 promise로 realm에서 설정한다.

  4. 다음 단계를 병렬로 실행한다:

    1. 비동기 작업 수행.

    2. environment가 정상적으로 ready가 되면, 태스크 큐에 등록하여 taskSource에 resolve environment의 ready promise를 수행한다.

    3. environment가 ready가 되지 못하면, 태스크 큐에 등록하여 taskSource에 reject environment의 ready promise를 "NetworkError" DOMException으로 거부한다.

  5. environment를 반환한다.

addBookmark는 연산이며, 사용자에게 현재 웹페이지를 북마크에 추가해달라고 요청합니다. 실제 디자인 작업에서 파생된 예시로, 환경 비동기성과 즉시 거부를 다루는 현실적인 시나리오를 보여줍니다.

interface I {
  Promise<undefined> addBookmark();
};

addBookmark() 메서드 단계:

  1. taskSource를 적절한 태스크 소스로 설정한다.

  2. 이 메서드가 명시적 사용자 동작의 결과로 호출되지 않았다면, 거부된 promise를 "SecurityError" DOMException으로 반환한다.

  3. 문서의 동작 모드가 standalone이면 거부된 promise를 "NotSupportedError" DOMException으로 반환한다.

  4. promise를 새로운 promise로 생성한다.

  5. info를 웹 애플리케이션의 메타데이터를 얻은 결과로 설정한다.

  6. 다음 단계를 병렬로 실행한다:

    1. info를 활용하여, 사용자 에이전트별 방식으로 최종 사용자가 북마크 추가 여부를 선택하도록 한다.

      1. 최종 사용자가 북마크 추가 요청을 중단(예: ESC 키, 취소 버튼 등)하면, 태스크 큐에 등록하여 taskSource에 reject promise를 "AbortError" DOMException으로 수행한다.

      2. 그 외의 경우, 태스크 큐에 등록하여 taskSource에 resolve promise를 수행한다.

  7. promise를 반환한다.

[SERVICE-WORKERS]의 여러 곳에서 모두 기다리는 promise 얻기(get a promise to wait for all)를 사용합니다. batchRequest는 그 용례 중 하나를 단순화한 예시입니다. 입력값으로 sequence 타입의 URL 목록을 받고, 각 URL을 fetch하여 생성된 sequence 타입의 Response 객체의 promise를 반환합니다. fetch 중 하나라도 실패하면, 해당 실패로 거부된 promise를 반환합니다.

interface I {
  Promise<sequence<Response>> batchRequest(sequence<USVString> urls);
};

batchRequest(urls) 메서드 단계:

  1. responsePromises를 « »로 설정한다.

  2. 각 urls의 url에 대해:

    1. p를 fetch() 함수에 url을 넣어 호출한 결과로 설정한다.

    2. 추가하여 p를 responsePromises에 넣는다.

  3. p를 모두 기다리는 promise 얻기로 responsePromises에 대해 호출한 결과로 설정한다.

  4. p를 반환한다.

3.2.25. Union 타입

IDL union 타입 값은 해당 union의 멤버 타입에 해당하는 자바스크립트 값으로 표현됩니다.

자바스크립트 값 V를 IDL union 타입 값으로 변환하려면 다음과 같이 합니다:

  1. union 타입이 undefined를 포함하고 V가 undefined라면, 고유한 undefined 값을 반환합니다.

  2. union 타입이 nullable 타입을 포함하고 V가 null 또는 undefined라면, IDL 값 null을 반환합니다.

  3. types를 union 타입의 평탄화된 멤버 타입으로 설정합니다.

  4. V가 null 또는 undefined라면:

    1. types에 dictionary 타입이 포함되어 있다면, V를 해당 dictionary 타입으로 변환한 결과를 반환합니다.

  5. V가 플랫폼 객체라면:

    1. types에 interface 타입이 포함되어 있고 V가 이를 구현한다면, V 객체를 참조하는 IDL 값을 반환합니다.

    2. types에 object가 포함되어 있다면, V 객체를 참조하는 IDL 값을 반환합니다.

  6. V가 Object이며, [[ArrayBufferData]] 내부 슬롯이 있고, IsSharedArrayBuffer(V)가 false라면:

    1. types에 ArrayBuffer가 포함되어 있다면, V를 ArrayBuffer로 변환한 결과를 반환합니다.

    2. types에 object가 포함되어 있다면, V 객체를 참조하는 IDL 값을 반환합니다.

  7. V가 Object이며, [[ArrayBufferData]] 내부 슬롯이 있고, IsSharedArrayBuffer(V)가 true라면:

    1. types에 SharedArrayBuffer가 포함되어 있다면, V를 SharedArrayBuffer로 변환한 결과를 반환합니다.

    2. types에 object가 포함되어 있다면, V 객체를 참조하는 IDL 값을 반환합니다.

  8. V가 Object이며, [[DataView]] 내부 슬롯이 있다면:

    1. types에 DataView가 포함되어 있다면, V를 DataView로 변환한 결과를 반환합니다.

    2. types에 object가 포함되어 있다면, V 객체를 참조하는 IDL 값을 반환합니다.

  9. V가 Object이며, [[TypedArrayName]] 내부 슬롯이 있다면:

    1. types에 typed array 타입이 포함되어 있고, 해당 타입 이름이 V의 [[TypedArrayName]] 내부 슬롯의 값과 같다면, V를 해당 타입으로 변환한 결과를 반환합니다.

    2. types에 object가 포함되어 있다면, V 객체를 참조하는 IDL 값을 반환합니다.

  10. IsCallable(V)가 true라면:

    1. types에 callback function 타입이 포함되어 있다면, V를 해당 callback function 타입으로 변환한 결과를 반환합니다.

    2. types에 object가 포함되어 있다면, V 객체를 참조하는 IDL 값을 반환합니다.

  11. V가 Object라면:

    1. types에 async sequence 타입이 포함되어 있다면

      1. types에 string 타입이 포함되어 있지 않거나, V에 [[StringData]] 내부 슬롯이 없다면,

        1. asyncMethod를 ? GetMethod(V, %Symbol.asyncIterator%)로 설정합니다.

        2. asyncMethod가 undefined가 아니면, IDL async sequence 값을 반환합니다. object는 V, method는 syncMethod, type은 "async"로 설정합니다.

        3. syncMethod를 ? GetMethod(V, %Symbol.iterator%)로 설정합니다.

        4. syncMethod가 undefined가 아니면, IDL async sequence 값을 반환합니다. object는 V, method는 syncMethod, type은 "sync"로 설정합니다.

    2. types에 sequence 타입이 포함되어 있다면

      1. method를 ? GetMethod(V, %Symbol.iterator%)로 설정합니다.

      2. method가 undefined가 아니면, 해당 타입의 시퀀스 생성 결과를 V와 method로 반환합니다.

    3. types에 frozen array 타입이 포함되어 있다면

      1. method를 ? GetMethod(V, %Symbol.iterator%)로 설정합니다.

      2. method가 undefined가 아니면, 해당 타입의 frozen array 생성 결과를 V와 method로 반환합니다.

    4. types에 dictionary 타입이 포함되어 있다면, V를 해당 dictionary 타입으로 변환한 결과를 반환합니다.

    5. types에 record 타입이 포함되어 있다면, V를 해당 record 타입으로 변환한 결과를 반환합니다.

    6. types에 callback interface 타입이 포함되어 있다면, V를 해당 callback interface 타입으로 변환한 결과를 반환합니다.

    7. types에 object가 포함되어 있다면, V 객체를 참조하는 IDL 값을 반환합니다.

  12. V가 Boolean 타입이라면:

    1. types에 boolean이 포함되어 있다면, V를 boolean으로 변환한 결과를 반환합니다.

  13. V가 Number 타입이라면:

    1. types에 numeric 타입이 포함되어 있다면, V를 해당 numeric 타입으로 변환한 결과를 반환합니다.

  14. V가 BigInt 타입이라면:

    1. types에 bigint가 포함되어 있다면, V를 bigint로 변환한 결과를 반환합니다.

  15. types에 string 타입이 포함되어 있다면, V를 해당 타입으로 변환한 결과를 반환합니다.

  16. types에 numeric 타입과 bigint가 포함되어 있다면, V를 해당 numeric 타입 또는 bigint로 변환한 결과를 반환합니다.

  17. types에 numeric 타입이 포함되어 있다면, V를 해당 numeric 타입으로 변환한 결과를 반환합니다.

  18. types에 boolean이 포함되어 있다면, V를 boolean으로 변환한 결과를 반환합니다.

  19. types에 bigint가 포함되어 있다면, V를 bigint로 변환한 결과를 반환합니다.

  20. TypeError를 throw합니다. TypeError.

IDL union 타입 값은 해당 union 값의 구체 타입(specific type)에 대한 변환 규칙에 따라 자바스크립트 값으로 변환됩니다. (자세한 내용은 § 3.2 JavaScript 타입 매핑 참조)

3.2.26. 버퍼 소스 타입

IDL ArrayBuffer 값은 해당 JavaScript 클래스의 객체로 표현됩니다. 해당 값이 연결된 [AllowResizable] 확장 속성을 갖지 않는 경우, JavaScript ArrayBuffer 객체 V 중 IsFixedLengthArrayBuffer(V)가 true인 것만을 기반으로 할 수 있습니다.

IDL SharedArrayBuffer 값은 해당 JavaScript 클래스의 객체로 표현됩니다. 해당 값이 연결된 [AllowResizable] 확장 속성을 갖지 않는 경우, JavaScript SharedArrayBuffer 객체 V 중 IsFixedLengthArrayBuffer(V)가 true인 것만을 기반으로 할 수 있습니다.

IDL 버퍼 뷰 타입의 값은 해당 JavaScript 클래스의 객체로 표현되며, 이러한 객체에는 다음과 같은 추가 제한이 적용됩니다.

JavaScript 값 V는 변환되어 IDL ArrayBuffer 값이 되며, 다음 알고리즘을 실행합니다:

  1. V가 Object가 아니거나, V에 [[ArrayBufferData]] 내부 슬롯이 없으면, 예외를 발생시킵니다. 그 예외는 TypeError입니다.

  2. IsSharedArrayBuffer(V)가 true이면, 예외를 발생시킵니다. 그 예외는 TypeError입니다.

  3. 변환 대상인 IDL 타입이 연결된 [AllowResizable] 확장 속성을 갖지 않고, IsFixedLengthArrayBuffer(V)가 false이면, 예외를 발생시킵니다. 그 예외는 TypeError입니다.

  4. IDL ArrayBuffer 값 중 V와 동일한 객체에 대한 참조인 값을 반환합니다.

JavaScript 값 V는 변환되어 IDL SharedArrayBuffer 값이 되며, 다음 알고리즘을 실행합니다:

  1. V가 Object가 아니거나, V에 [[ArrayBufferData]] 내부 슬롯이 없으면, 예외를 발생시킵니다. 그 예외는 TypeError입니다.

  2. IsSharedArrayBuffer(V)가 false이면, 예외를 발생시킵니다. 그 예외는 TypeError입니다.

  3. 변환 대상인 IDL 타입이 연결된 [AllowResizable] 확장 속성을 갖지 않고, IsFixedLengthArrayBuffer(V)가 false이면, 예외를 발생시킵니다. 그 예외는 TypeError입니다.

  4. IDL SharedArrayBuffer 값 중 V와 동일한 객체에 대한 참조인 값을 반환합니다.

JavaScript 값 V는 변환되어 IDL DataView 값이 되며, 다음 알고리즘을 실행합니다:

  1. V가 Object가 아니거나, V에 [[DataView]] 내부 슬롯이 없으면, 예외를 발생시킵니다. 그 예외는 TypeError입니다.

  2. 변환 대상인 IDL 타입이 연결된 [AllowShared] 확장 속성을 갖지 않고, IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) 가 true이면, 예외를 발생시킵니다. 그 예외는 TypeError입니다.

  3. 변환 대상인 IDL 타입이 연결된 [AllowResizable] 확장 속성을 갖지 않고, IsFixedLengthArrayBuffer(V.[[ViewedArrayBuffer]]) 가 false이면, 예외를 발생시킵니다. 그 예외는 TypeError입니다.

  4. IDL DataView 값 중 V와 동일한 객체에 대한 참조인 값을 반환합니다.

JavaScript 값 V는 변환되어 IDL Int8Array, Int16Array, Int32Array, Uint8Array, Uint16Array, Uint32Array, Uint8ClampedArray, BigInt64Array, BigUint64Array, Float16Array, Float32Array, 또는 Float64Array 값으로 다음 알고리즘을 실행하여 변환됩니다:

  1. T를 V가 변환되는 대상 IDL 타입으로 둡니다.

  2. V가 Object가 아니거나, V에 [[TypedArrayName]] 내부 슬롯 중 T의 이름과 같은 값을 가진 것이 없다면, 예외를 발생시킵니다. 그 예외는 TypeError입니다.

  3. 변환 대상인 IDL 타입이 연결된 [AllowShared] 확장 속성을 갖지 않고, IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) 가 true이면, 예외를 발생시킵니다. 그 예외는 TypeError입니다.

  4. 변환 대상인 IDL 타입이 연결된 [AllowResizable] 확장 속성을 갖지 않고, IsFixedLengthArrayBuffer(V.[[ViewedArrayBuffer]]) 가 false이면, 예외를 발생시킵니다. 그 예외는 TypeError입니다.

  5. V와 동일한 객체에 대한 참조인 타입 T의 IDL 값을 반환합니다.

IDL buffer source 타입의 값을 자바스크립트 값으로 변환한 결과는 해당 IDL 값이 참조하는 객체와 동일한 객체를 참조하는 Object 값입니다.

생성을 하려면 ArrayBuffer를 바이트 시퀀스 bytes와 realm realm에서 생성합니다:
  1. jsArrayBuffer를 ? AllocateArrayBuffer(realm.[[Intrinsics]].[[%ArrayBuffer%]], bytes의 길이)로 설정합니다.

  2. arrayBuffer를 변환을 통해 jsArrayBuffer를 ArrayBuffer 타입의 IDL 값으로 변환합니다.

  3. bytes를 arrayBuffer에 작성합니다.

  4. arrayBuffer를 반환합니다.

생성을 하려면 SharedArrayBuffer를 바이트 시퀀스 bytes와 realm realm에서 생성합니다:
  1. jsSharedArrayBuffer를 ? AllocateSharedArrayBuffer(realm.[[Intrinsics]].[[%SharedArrayBuffer%]], bytes의 길이)로 설정합니다.

  2. sharedArrayBuffer를 변환을 통해 jsSharedArrayBuffer를 SharedArrayBuffer 타입의 IDL 값으로 변환합니다.

  3. bytes를 sharedArrayBuffer에 작성합니다.

  4. sharedArrayBuffer를 반환합니다.

생성을 하려면 ArrayBufferView 타입 중 하나를 바이트 시퀀스 bytes와 realm realm에서 생성합니다:
  1. 단, 타입이 DataView가 아니라면, bytes의 길이를 해당 타입의 요소 크기로 나눈 나머지가 0이어야 합니다.

  2. arrayBuffer를 생성을 통해 ArrayBuffer로 bytes와 realm에서 생성합니다.

  3. jsArrayBuffer를 변환을 통해 arrayBuffer를 자바스크립트 값으로 변환합니다.

  4. constructor를 realm.[[Intrinsics]]에서 생성할 ArrayBufferView 타입에 맞는 생성자로 설정합니다.

  5. jsView를 ! Construct(constructor, « jsArrayBuffer »)로 생성합니다.

  6. 변환을 통해 jsView를 해당 타입으로 변환한 결과를 반환합니다.

버퍼 소스의 바이트 복사 얻기는 buffer source 타입 인스턴스 bufferSource에 대해 다음 단계를 수행합니다:
  1. jsBufferSource를 변환을 통해 bufferSource를 자바스크립트 값으로 변환합니다.

  2. jsArrayBuffer를 jsBufferSource로 설정합니다.

  3. offset을 0으로 설정합니다.

  4. length을 0으로 설정합니다.

  5. jsBufferSource가 [[ViewedArrayBuffer]] 내부 슬롯을 가지면:

    1. jsArrayBuffer를 jsBufferSource.[[ViewedArrayBuffer]]로 설정합니다.

    2. offset을 jsBufferSource.[[ByteOffset]]로 설정합니다.

    3. length을 jsBufferSource.[[ByteLength]]로 설정합니다.

  6. 그 외의 경우:

    1. jsBufferSource는 ArrayBuffer 또는 SharedArrayBuffer 객체여야 합니다.

    2. length을 jsBufferSource.[[ArrayBufferByteLength]]로 설정합니다.

  7. IsDetachedBuffer(jsArrayBuffer)가 true면 빈 바이트 시퀀스를 반환합니다.

  8. bytes를 바이트 시퀀스로 생성하며, 길이는 length로 설정합니다.

  9. 각 i에 대해, 범위 offset부터 offset + length까지에서 끝값을 제외하고, 설정 대상인 bytes[i − offset]을 GetValueFromBuffer(jsArrayBuffer, i, Uint8, true, Unordered)로 설정합니다.

  10. bytes를 반환합니다.

바이트 길이는 buffer source 타입 인스턴스 bufferSource에 대해 다음 단계의 결과입니다:
  1. jsBufferSource를 변환을 통해 bufferSource를 자바스크립트 값으로 변환합니다.

  2. jsBufferSource가 [[ViewedArrayBuffer]] 내부 슬롯을 가지면, jsBufferSource.[[ByteLength]]를 반환합니다.

  3. jsBufferSource.[[ArrayBufferByteLength]]를 반환합니다.

기저 버퍼(underlying buffer)란 버퍼 소스 타입 인스턴스 bufferSource에 대해 다음 단계로 반환되는 값을 의미합니다:
  1. bufferSource가 버퍼 타입 인스턴스라면 bufferSource를 반환합니다.

  2. jsBufferView를 IDL에서 자바스크립트 값으로 변환한 bufferSource의 결과로 설정합니다.

  3. jsBuffer를 jsBufferView.[[ViewedArrayBuffer]]로 설정합니다.

  4. IsSharedArrayBuffer(jsBuffer)가 false라면, 자바스크립트 값을 IDL 값으로 변환하여 jsBuffer를 ArrayBuffer 타입으로 반환합니다.

  5. 자바스크립트 값을 IDL 값으로 변환하여 jsBuffer를 SharedArrayBuffer 타입으로 반환합니다.

쓰기(write)란 바이트 시퀀스(byte sequence) bytes를 버퍼 타입 인스턴스 arrayBuffer에 쓸 때, 옵셔널로 startingOffset (기본값 0)을 받을 수 있습니다:
  1. jsArrayBuffer를 IDL에서 자바스크립트 값으로 변환한 arrayBuffer의 결과로 설정합니다.

  2. 단언: bytes의 길이(length) ≤ jsArrayBuffer.[[ArrayBufferByteLength]] − startingOffset.

  3. 각 i에 대해, 범위 startingOffset부터 startingOffset + bytes의 길이까지에서 끝값을 제외하고, 다음을 수행합니다: SetValueInBuffer(jsArrayBuffer, i, Uint8, bytes[i - startingOffset], true, Unordered).

쓰기(write)란 바이트 시퀀스(byte sequence) bytes를 ArrayBufferView view에 쓸 때, 옵셔널로 startingOffset (기본값 0)을 받을 수 있습니다:
  1. jsView를 IDL에서 자바스크립트 값으로 변환한 view의 결과로 설정합니다.

  2. 단언: bytes의 길이 ≤ jsView.[[ByteLength]] − startingOffset.

  3. 단언: view가 DataView가 아닐 경우, bytes의 길이를 modulo view의 타입의 요소 크기(element size)로 나눈 나머지가 0임을 보장합니다.

  4. arrayBuffer를 자바스크립트 값을 IDL 값으로 변환하여 jsView.[[ViewedArrayBuffer]]를 ArrayBuffer 타입으로 설정합니다.

  5. 쓰기(write)를 bytes와 arrayBuffer로, startingOffset을 jsView.[[ByteOffset]] + startingOffset으로 하여 수행합니다.

버퍼 소스 타입 인스턴스에 데이터를 쓸 때는, 아래 데이터가 예상치 못한 시점에 스크립트 작성자나 다른 API에 의해 쉽게 변경될 수 있으므로 명세 작성 시 각별히 주의해야 합니다. 특히 SharedArrayBuffer 객체가 관련된 경우 더욱 그렇습니다.

공유되지 않은 경우, 보다 권장되는 패턴은 transfer(이전)를 먼저 수행하여 ArrayBuffer 인스턴스의 쓰기가 다른 수정과 겹치지 않도록 보장한 뒤, 필요에 따라 새 ArrayBuffer 인스턴스를 작성자 코드에 제공하는 것입니다. 또는 버퍼 소스가 가진 바이트의 복사본을 얻어 해당 바이트를 수정한 뒤, 이를 사용해 생성한 새로운 ArrayBuffer나 ArrayBufferView 를 작성자 코드에 제공할 수 있습니다.

detach(분리)란 ArrayBuffer arrayBuffer에 대해 다음을 수행합니다:
  1. jsArrayBuffer를 IDL에서 자바스크립트 값으로 변환한 arrayBuffer의 결과로 설정합니다.

  2. ? DetachArrayBuffer(jsArrayBuffer)를 수행합니다.

만약 jsArrayBuffer가 [[ArrayBufferDetachKey]]가 undefined가 아닌 경우, (예: WebAssembly.Memory의 buffer 속성값 등) 예외가 발생합니다. [WASM-JS-API-1]

이미 detached(분리됨)된 버퍼를 detach하는 것은 아무 효과가 없습니다.

버퍼 소스 타입 인스턴스 bufferSource가 detached(분리됨)인지 여부는 다음 단계가 true를 반환하는지로 결정합니다:
  1. jsArrayBuffer를 IDL에서 자바스크립트 값으로 변환한 bufferSource의 결과로 설정합니다.

  2. jsArrayBuffer가 [[ViewedArrayBuffer]] 내부 슬롯을 가진 경우, jsArrayBuffer를 jsArrayBuffer.[[ViewedArrayBuffer]]로 설정합니다.

  3. IsDetachedBuffer(jsArrayBuffer)를 반환합니다.

버퍼 소스 타입 인스턴스 bufferSource가 transferable(이전 가능)인지 여부는 다음 단계가 true를 반환하는지로 결정합니다:
  1. jsArrayBuffer를 IDL에서 자바스크립트 값으로 변환한 bufferSource의 결과로 설정합니다.

  2. jsArrayBuffer가 [[ViewedArrayBuffer]] 내부 슬롯을 가진 경우, jsArrayBuffer를 jsArrayBuffer.[[ViewedArrayBuffer]]로 설정합니다.

  3. IsSharedArrayBuffer(jsArrayBuffer)가 true이면 false 반환.

  4. IsDetachedBuffer(jsArrayBuffer)가 true이면 false 반환.

  5. jsArrayBuffer.[[ArrayBufferDetachKey]]가 undefined가 아니면 false 반환.

  6. true 반환.

transfer(이전)란 ArrayBuffer arrayBuffer를, 옵셔널하게 realm targetRealm에 이전할 때:
  1. jsArrayBuffer를 IDL에서 자바스크립트 값으로 변환한 arrayBuffer의 결과로 설정합니다.

  2. IsDetachedBuffer(jsArrayBuffer)가 true면, TypeError를 throw합니다. TypeError.

  3. arrayBufferData를 jsArrayBuffer.[[ArrayBufferData]]로 설정합니다.

  4. arrayBufferByteLength를 jsArrayBuffer.[[ArrayBufferByteLength]]로 설정합니다.

  5. ? DetachArrayBuffer(jsArrayBuffer)를 수행합니다.

  6. targetRealm이 없으면 targetRealm을 현재 realm으로 설정합니다.

  7. jsTransferred를 ? AllocateArrayBuffer(targetRealm.[[Intrinsics]].[[%ArrayBuffer%]], 0)로 설정합니다.

  8. jsTransferred.[[ArrayBufferData]]를 arrayBufferData로 설정합니다.

  9. jsTransferred.[[ArrayBufferByteLength]]를 arrayBufferByteLength로 설정합니다.

  10. 자바스크립트 값을 IDL 값으로 변환하여 jsTransferred를 ArrayBuffer 타입으로 반환합니다.

다음과 같은 상황에서는 예외가 발생합니다:
  • arrayBuffer가 detached(분리됨)될 수 없는 경우, 해당 알고리즘 설명 (참고)에 명시된 이유 때문입니다;

  • arrayBuffer가 이미 detached(분리됨)인 경우;

  • realm에 충분한 메모리를 할당할 수 없을 때. 일반적으로 이는 realm이 arrayBuffer가 할당된 에이전트 클러스터(agent cluster)와 다를 때만 발생합니다. 동일한 에이전트 클러스터인 경우에는 구현체가 백킹 포인터만 변경하여 더 나은 성능과 할당 없이 동일한 관찰 가능한 결과를 얻을 수 있습니다.

3.2.27. 불변 배열 — FrozenArray<T>

불변 배열 타입의 값은 불변(frozen) JavaScript Array 객체 참조로 표현됩니다.

JavaScript 값 V를 변환하여 IDL FrozenArray<T> 값으로 만드는 알고리즘:

  1. values를 변환하여 V를 IDL 타입 sequence<T>으로 변환한 결과로 설정한다.

  2. 불변 배열 생성 알고리즘에 values를 넣어 반환한다.

불변 배열 생성 알고리즘: 타입 T의 값 시퀀스에 대해 아래 단계를 실행한다:

  1. array를 IDL → JavaScript 값 변환 알고리즘으로 타입 T 값 시퀀스를 변환한 결과로 설정한다.

  2. ! SetIntegrityLevel(array, "frozen")을 수행한다.

  3. array를 반환한다.

IDL → JavaScript 값 변환 알고리즘 결과로 IDL FrozenArray<T> 값을 JavaScript 값으로 변환하면, 해당 IDL FrozenArray<T>이 참조하는 같은 객체를 참조하는 Object 값이 된다.

3.2.27.1. 이터러블로부터 불변 배열 생성

이터러블 iterable과 이터레이터 getter method가 주어졌을 때, IDL 타입 FrozenArray<T>를 생성하는 알고리즘:

  1. values를 이터러블로부터 시퀀스 생성 알고리즘에 iterable과 method를 넣어 타입 sequence<T>로 변환한 결과로 설정한다.

  2. 불변 배열 생성 알고리즘에 values를 넣어 반환한다.

3.2.28. 관측 배열 — ObservableArray<T>

관측 배열 타입의 값은 observable array exotic object로 표현됩니다.

일반적인 변환 알고리즘 대신, 관측 배열 타입은 attribute getter와 attribute setter 알고리즘의 일부로 특별하게 처리됩니다.

JavaScript 바인딩에서 플랫폼 객체를 나타내는 JavaScript 객체는 backing observable array exotic object를 각 정규 attribute에 대해 관측 배열 타입에 대해 가집니다. 이는 attribute 정의 알고리즘의 일부로 생성 및 관리됩니다.

JavaScript 바인딩에서 관측 배열 attribute의 backing list는, 플랫폼 객체 obj와 attribute attribute가 주어졌을 때 다음 알고리즘에 의해 반환되는 list입니다:
  1. 단언: obj는 구현한 interface에 정규 attribute attribute가 있다.

  2. oa를 obj의 backing observable array exotic object로 attribute에 대해 설정한다.

  3. oa.[[ProxyHandler]].[[BackingList]]를 반환한다.

3.3. 확장 어트리뷰트

이 절에서는 JavaScript 바인딩에 영향을 주는 여러 확장 어트리뷰트를 정의합니다.

3.3.1. [AllowResizable]

만약 [AllowResizable] 확장 속성이 잠재적으로 널 허용 버퍼 타입에 나타나면, 해당하는 JavaScript의 각각 대응하는 ArrayBuffer 또는 SharedArrayBuffer 객체가 크기 조정 가능하도록 허용하는 새 IDL 타입을 만듭니다.

만약 [AllowResizable] 확장 속성이 잠재적으로 널 허용 버퍼 뷰 타입에 나타나고 [AllowShared] 확장 속성은 나타나지 않으면, 새 IDL 타입을 만들어 버퍼 뷰 타입이 JavaScript ArrayBuffer 중 크기 조정 가능한 것을 기반으로 할 수 있게 하며, 고정 길이의 ArrayBuffer만을 기반으로 하도록 제한하지 않습니다.

만약 [AllowResizable] 확장 속성과 [AllowShared] 확장 속성이 모두 잠재적으로 널 허용 버퍼 뷰 타입에 나타나면, 새 IDL 타입을 만들어 버퍼 뷰 타입이 추가로 JavaScript SharedArrayBuffer 중 확장 가능한 것을 기반으로 할 수 있게 합니다.

[AllowResizable] 확장 속성은 반드시 인수를 받지 않아야 합니다.

잠재적으로 널 허용 버퍼 소스 타입이 아닌 타입은 [AllowResizable] 확장 속성과 연결되어서는 안 됩니다.

[AllowResizable]의 사용에 수반되는 구체적인 요구 사항은 § 3.2.26 버퍼 소스 타입의 JavaScript 값을 IDL 버퍼 소스 타입으로 변환하는 규칙을 참조하십시오.

[AllowResizable] 및 [AllowShared] 둘 다의 사용 예는 § 3.3.2 [AllowShared]의 예를 참조하십시오.

3.3.2. [AllowShared]

만약 [AllowShared] 확장 속성이 잠재적으로 널 허용 버퍼 뷰 타입에 나타나면, 객체가 다음을 기반으로 할 수 있게 하는 새 IDL 타입을 만듭니다: SharedArrayBuffer 즉, ArrayBuffer만을 기반으로 하도록 제한하지 않습니다.

[AllowShared] 확장 속성은 반드시 인수를 받지 않아야 합니다.

잠재적으로 널 허용 버퍼 뷰 타입이 아닌 타입은 [AllowShared] 확장 속성과 연결되어서는 안 됩니다.

[AllowShared]의 사용에 수반되는 구체적인 요구 사항은 § 3.2.26 버퍼 소스 타입의 JavaScript 값을 IDL 버퍼 뷰 타입으로 변환하는 규칙을 참조하십시오.

다음 IDL 프래그먼트는 [AllowResizable]와 [AllowShared] 확장 어트리뷰트의 조합을 보여줍니다:
[Exposed=Window]
interface ExampleBufferFeature {
  undefined writeInto(ArrayBufferView dest);
  undefined writeIntoResizable([AllowResizable] ArrayBufferView dest);
  undefined writeIntoShared([AllowShared] ArrayBufferView dest);
  undefined writeIntoSharedResizable([AllowResizable, AllowShared] ArrayBufferView dest);
};

이 정의에서,

3.3.3. [Clamp]

[Clamp] 확장 속성이 잠재적으로 널 허용 정수 타입에 나타나면, JavaScript Number가 IDL 타입으로 변환될 때 범위를 벗어난 값에 모듈로 연산을 사용하는 연산자를 사용하는 대신 유효한 값의 범위로 제한되도록 하는 새로운 IDL 타입을 만듭니다(ToInt32, ToUint32 등).

[Clamp] 확장 속성은 반드시 인수를 받지 않아야 합니다.

[Clamp] 확장 속성으로 주석이 지정된 타입은 읽기 전용 속성에 나타나서는 안 됩니다. 타입은 연결된 다음 두 [Clamp] 및 [EnforceRange] 확장 속성을 모두 가져서는 안 됩니다. 다음에 해당하지 않는 타입은 잠재적으로 널 허용 정수 타입이 아니면 [Clamp] 확장 속성과 연결되어서는 안 됩니다.

JavaScript 값을 다양한 IDL 정수 타입으로 변환하는 규칙은 § 3.2.4 정수 타입을 참조하십시오. 다음 사용에 수반되는 구체적인 요구 사항에 관한 것입니다: [Clamp].

다음 IDL 프래그먼트에서는 세 개의 octet 인자를 받는 두 개의 operation이 선언되어 있습니다. 하나는 세 인자 모두에 [Clamp] 확장 어트리뷰트를 사용하고, 다른 하나는 사용하지 않습니다:

[Exposed=Window]
interface GraphicsContext {
  undefined setColor(octet red, octet green, octet blue);
  undefined setColorClamped([Clamp] octet red, [Clamp] octet green, [Clamp] octet blue);
};

setColorClamped를 범위를 벗어난 Number 값과 함께 호출하면, octet 타입의 범위 [0, 255]로 값을 클램프합니다.

// GraphicsContext 인스턴스를 얻음.
var context = getGraphicsContext();

// [Clamp]가 없는 버전은 ToUint8을 사용하여 Number를 octet으로 변환합니다.
// 이는 setColor(255, 255, 1)을 호출한 것과 같습니다.
context.setColor(-1, 255, 257);

// 범위 초과 값을 setColorClamped에 전달.
// 이는 setColorClamped(0, 255, 255)를 호출한 것과 같습니다.
context.setColorClamped(-1, 255, 257);

3.3.4. [CrossOriginIsolated]

[CrossOriginIsolated] 확장 어트리뷰트가 interface, partial interface, interface mixin, partial interface mixin, callback interface, namespace, partial namespace, interface member, interface mixin member, 또는 namespace member에 나타나면, 해당 구성 요소가 노출되는 환경이 cross-origin isolated capability 가 true일 때만 노출됨을 나타냅니다. [CrossOriginIsolated] 확장 어트리뷰트는 다른 구성 요소에 사용하면 안 됩니다.

[CrossOriginIsolated] 확장 어트리뷰트는 인자를 가지지 않아야 합니다.

[CrossOriginIsolated] 가 오버로드된 operation에 나타나면, 모든 오버로드에 반드시 나타나야 합니다.

[CrossOriginIsolated] 확장 어트리뷰트는 다음 경우 모두에 명시될 수 없습니다:

참고: 이는 [CrossOriginIsolated] 확장 어트리뷰트를 멤버에 추가해도 정의 전체에 이미 [CrossOriginIsolated] 확장 어트리뷰트가 있으면 멤버의 노출 범위가 추가로 제한되지 않기 때문입니다.

[CrossOriginIsolated] 확장 어트리뷰트가 없는 interface는 [CrossOriginIsolated]를 명시한 다른 interface를 상속하면 안 됩니다.

다음 IDL 프래그먼트는 모든 컨텍스트에서 실행 가능한 operation 1개와, cross-origin isolated 컨텍스트에서만 실행 가능한 operation 2개를 가진 interface를 정의합니다.

[Exposed=Window]
interface ExampleFeature {
  // 모든 컨텍스트에서 성공
  Promise <Result> calculateNotSoSecretResult();

  // 이 operation은 비격리 컨텍스트에 노출되지 않습니다. 해당 컨텍스트에서 ExampleFeature.prototype에 "calculateSecretResult" 속성이 없습니다.
  [CrossOriginIsolated] Promise<Result> calculateSecretResult();

  // 마찬가지로 이 attribute도 비격리 컨텍스트에 노출되지 않으며,
  // ExampleFeature.prototype에 "secretBoolean" 속성이 없습니다.
  [CrossOriginIsolated] readonly attribute boolean secretBoolean;
};

// HighResolutionTimer는 비격리 컨텍스트에 노출되지 않으며, 멤버도 노출되지 않습니다.
// 해당 컨텍스트에서 Window에 "HighResolutionTimer" 속성이 없습니다.
[Exposed=Window, CrossOriginIsolated]
interface HighResolutionTimer {
  DOMHighResTimeStamp getHighResolutionTime();
};

// 아래 interface mixin 멤버는 비격리 컨텍스트에서는 노출되지 않습니다. 즉, 비격리 컨텍스트에서는 ExampleFeature.prototype에 "snap" 속성이 없습니다.
[CrossOriginIsolated]
interface mixin Snapshotable {
  Promise<boolean> snap();
};
ExampleFeature includes Snapshotable;

// 반면, 아래 interface mixin 멤버는 호스트 interface에 [CrossOriginIsolated] 확장 어트리뷰트가 없으면 비격리 컨텍스트에서도 노출됩니다.
// 즉, 비격리 컨텍스트에서는 ExampleFeature.prototype에 "log" 속성이 있습니다.
interface mixin Loggable {
  Promise<boolean> log();
};
ExampleFeature includes Loggable;

3.3.5. [Default]

[Default] 확장 어트리뷰트가 정규 operation에 나타나면, 해당 operation이 호출될 때 적절한 기본 메서드 단계를 수행해야 함을 나타냅니다.

[Default] 확장 어트리뷰트는 인자를 가지지 않아야 합니다.

[Default] 확장 어트리뷰트는 정규 operation 외에는 사용할 수 없으며, 해당 operation에 기본 메서드 단계가 정의되어 있어야 합니다.

예시로, [Default] 확장 어트리뷰트는 toJSON 정규 operation에 사용할 수 있습니다:

[Exposed=Window]
interface Animal {
  attribute DOMString name;
  attribute unsigned short age;
  [Default] object toJSON();
};

[Exposed=Window]
interface Human : Animal {
  attribute Dog? pet;
  [Default] object toJSON();
};

[Exposed=Window]
interface Dog : Animal {
  attribute DOMString? breed;
};

JavaScript 바인딩에서는 Animal, Human, 그리고 상속을 통해 Dog 객체에도 toJSON() 메서드가 존재합니다:

// Human 인스턴스를 얻음.
var alice = getHuman();

// 아래와 같은 객체로 평가됨 ("pet"은 Dog 인스턴스를 그대로 갖고 있음):
//
// {
//   name: "Alice",
//   age: 59,
//   pet: Dog
// }
alice.toJSON();

// 아래와 같은 객체로 평가됨 ("breed"는 Dog 인터페이스가 기본 toJSON 단계를 사용하지 않으므로 없음):
//
// {
//   name: "Tramp",
//   age: 6
// }
alice.pet.toJSON();

// 아래와 같은 문자열로 평가됨:
// '{"name":"Alice","age":59,"pet":{"name":"Tramp","age":6}}'
JSON.stringify(alice);

3.3.6. [EnforceRange]

[EnforceRange] 확장 속성이 잠재적으로 널 허용 정수 타입에 나타나면, JavaScript Number가 IDL 타입으로 변환될 때, 범위를 벗어난 값은 모듈로 연산을 사용하는 연산자를 사용하여 유효한 값으로 변환되는 대신 예외가 발생하도록 하는 새 IDL 타입을 만듭니다 (ToInt32, ToUint32 등). Number는 범위와 비교하여 검사되기 전에 0을 향해 반올림됩니다.

[EnforceRange] 확장 속성은 반드시 인수를 받지 않아야 합니다.

[EnforceRange] 확장 속성으로 주석이 지정된 타입은 읽기 전용 속성에 나타나서는 안 됩니다. 타입은 [Clamp] 및 [EnforceRange] 확장 속성 모두와 연결되어서는 안 됩니다. 다음에 해당하지 않는 타입은 잠재적으로 널 허용 정수 타입이 아니면 [EnforceRange] 확장 속성과 연결되어서는 안 됩니다.

JavaScript 값을 다양한 IDL 정수 타입으로 변환하는 규칙은 § 3.2 JavaScript 타입 매핑에서 참조하시기 바라며, 이는 [EnforceRange]의 사용에 수반되는 구체적인 요구 사항을 설명합니다.

다음 IDL 프래그먼트에서는 세 개의 octet 인자를 받는 두 개의 operation이 선언되어 있습니다. 하나는 세 인자 모두에 [EnforceRange] 확장 어트리뷰트를 사용하고, 다른 하나는 사용하지 않습니다:

[Exposed=Window]
interface GraphicsContext {
  undefined setColor(octet red, octet green, octet blue);
  undefined setColorEnforcedRange([EnforceRange] octet red, [EnforceRange] octet green, [EnforceRange] octet blue);
};

IDL의 JavaScript 구현에서 setColorEnforcedRange를 범위를 벗어난 Number 값과 함께 호출하면, octet 타입의 범위를 벗어나므로 예외가 발생합니다.

// GraphicsContext 인스턴스를 얻음.
var context = getGraphicsContext();

// [EnforceRange]가 없는 버전은 ToUint8을 사용하여 Number를 octet으로 변환합니다.
// 이는 setColor(255, 255, 1)을 호출한 것과 같습니다.
context.setColor(-1, 255, 257);

// setColorEnforcedRange를 호출하면 Number가 0 방향으로 반올림됩니다.
// 이는 setColor(0, 255, 255)를 호출한 것과 같습니다.
context.setColorEnforcedRange(-0.9, 255, 255.2);

// 아래는 예외(TypeError)를 발생시킵니다. 반올림 후에도 첫 번째와 세 번째 인자가 범위 밖에 있기 때문입니다.
context.setColorEnforcedRange(-1, 255, 256);

3.3.7. [Exposed]

[Exposed] 확장 어트리뷰트가 interface, partial interface, interface mixin, partial interface mixin, callback interface, namespace, partial namespace, 또는 개별 interface member, interface mixin member, 또는 namespace member에 나타나면, 해당 구성요소가 특정 글로벌 인터페이스 집합에 노출됨을 의미합니다.

[Exposed] 확장 어트리뷰트는 식별자, 식별자 리스트 또는 와일드카드를 가져야 합니다. 명시된 각 식별자는 어떤 interface의 글로벌 이름이어야 하며, 중복되면 안 됩니다.

자신의 노출 집합(own exposure set) 은 식별자들의 집합이거나, 특수 값 *입니다. 정의는 다음과 같습니다:

[Exposed] 확장 어트리뷰트가 식별자 I를 가질 때

자신의 노출 집합은 집합 « I » 입니다.

[Exposed] 확장 어트리뷰트가 식별자 리스트 I를 가질 때

자신의 노출 집합은 집합 I 입니다.

[Exposed] 확장 어트리뷰트가 와일드카드를 가질 때

자신의 노출 집합은 * 입니다.

[Exposed=*]는 신중하게 사용해야 합니다. API가 새로운 기능을 노출하지 않을 때만 적합합니다. API가 일부 환경에서 제한되거나 비활성화될 수 있다면, 글로벌을 명시적으로 리스트하는 것이 더 바람직합니다.

노출 집합 교집합은 구성 요소 C와 interface-or-null H에 대해 다음과 같이 정의됩니다:

  1. 단언: C는 interface member, interface mixin member, namespace member, partial interface, partial interface mixin, partial namespace, 또는 interface mixin이다.

  2. 단언: H는 interface 또는 null이다.

  3. H가 null이면, C의 자신의 노출 집합을 반환한다.

  4. C의 자신의 노출 집합이 *이면, H의 노출 집합을 반환한다.

  5. H의 노출 집합이 *이면, C의 자신의 노출 집합을 반환한다.

  6. C의 자신의 노출 집합과 H의 노출 집합의 교집합을 반환한다.

구성 요소 C의 노출 집합(exposure set)을 얻으려면, 다음 단계를 수행합니다:
  1. 단언: C는 interface, callback interface, namespace, interface member, interface mixin member, 또는 namespace member이다.

  2. H를 C가 interface mixin member일 경우 호스트 인터페이스로, 그렇지 않으면 null로 설정한다.

  3. C가 interface member, interface mixin member, 또는 namespace member라면:

    1. [Exposed] 확장 어트리뷰트가 C에 명시되어 있으면, 노출 집합 교집합을 C와 H로 반환한다.

    2. C를 interface, partial interface, interface mixin, partial interface mixin, namespace, 또는 partial namespace의 C로 설정한다.

  4. C가 partial interface, partial interface mixin, 또는 partial namespace일 경우:

    1. [Exposed] 확장 어트리뷰트가 C에 명시되어 있으면, 노출 집합 교집합을 C와 H로 반환한다.

    2. C를 원래 interface, interface mixin, 또는 namespace 정의의 C로 설정한다.

  5. C가 interface mixin일 경우:

    1. 단언: H는 null이 아니다.

    2. [Exposed] 확장 어트리뷰트가 C에 명시되어 있으면, 노출 집합 교집합을 C와 H로 반환한다.

    3. C를 H로 설정한다.

  6. 단언: C는 interface, callback interface, 또는 namespace이다.

  7. 단언: [Exposed] 확장 어트리뷰트가 C에 명시되어 있다.

  8. C의 자신의 노출 집합을 반환한다.

[Exposed] 가 오버로드된 operation에 나타나면, 모든 오버로드에 동일하게 나타나야 합니다.

[Exposed] 확장 어트리뷰트는 interface member, interface mixin member, 또는 namespace member에, 그리고 partial interface, partial interface mixin, 또는 partial namespace 그 멤버가 선언된 정의 모두에 명시될 수 없습니다.

참고: [Exposed] 확장 어트리뷰트를 partial interface, partial interface mixin, 또는 partial namespace에 추가하는 것은 해당 정의의 각 멤버에 어노테이션하는 약식 표현입니다.

[Exposed] 가 partial interface 또는 partial namespace에 나타나면, partial의 자신의 노출 집합은 partial의 원래 interface 또는 namespace의 노출 집합의 부분집합이어야 합니다.

[Exposed] 가 interface member 또는 namespace member에 나타나면, member의 노출 집합은 해당 interface 또는 namespace의 노출 집합의 부분집합이어야 합니다.

[Exposed] 가 partial interface mixin과 그 원래 interface mixin 모두에 나타나면, partial interface mixin의 자신의 노출 집합은 interface mixin의 자신의 노출 집합의 부분집합이어야 합니다.

[Exposed] 가 interface mixin member와 interface mixin 모두에 나타나면, interface mixin member의 자신의 노출 집합은 interface mixin의 자신의 노출 집합의 부분집합이어야 합니다.

interface X가 다른 interface Y를 상속하면, X의 노출 집합은 Y의 노출 집합의 부분집합이어야 합니다.

참고: interface mixin은 여러 interface에 포함될 수 있으므로, 그 멤버의 노출 집합은 그것을 포함하는 interface에 따라 결정된다. interface mixin member, partial interface mixin, 또는 interface mixin에 [Exposed] 확장 어트리뷰트가 있으면, 해당 interface mixin member의 노출 집합은 해당 구성 요소의 자신의 노출 집합과 호스트 인터페이스의 노출 집합의 교집합이 된다. 그렇지 않으면 호스트 인터페이스의 노출 집합이 된다.

interface, callback interface, namespace, 또는 member construct는 주어진 realm realm에서 다음 단계가 true를 반환할 때 노출됨(exposed) 상태입니다:
  1. construct의 노출 집합이 *가 아니고, realm.[[GlobalObject]]가 construct의 노출 집합에 포함된 interface를 구현하지 않는다면, false를 반환한다.

  2. realm의 설정 객체가 보안 컨텍스트가 아니고, construct가 [SecureContext]에서 조건부 노출됨 상태라면, false를 반환한다.

  3. realm의 설정 객체의 cross-origin isolated capability가 false이고, construct가 [CrossOriginIsolated]에서 조건부 노출됨 상태라면, false를 반환한다.

  4. true를 반환한다.

interface, callback interface, namespace, 또는 member construct가 주어진 확장 어트리뷰트 exposure condition에서 조건부 노출됨(conditionally exposed) 상태인지 판단하는 단계:
  1. 단언: construct는 interface, callback interface, namespace, interface member, interface mixin member, 또는 namespace member이다.

  2. H를 construct가 interface mixin member일 경우 호스트 인터페이스로, 그렇지 않으면 null로 설정한다.

  3. construct가 interface member, interface mixin member, 또는 namespace member라면:

    1. exposure condition 확장 어트리뷰트가 construct에 명시되어 있으면, true를 반환한다.

    2. 그렇지 않으면 construct를 interface, partial interface, interface mixin, partial interface mixin, namespace, 또는 partial namespace의 construct로 설정한다.

  4. construct가 partial interface, partial interface mixin, 또는 partial namespace일 경우:

    1. exposure condition 확장 어트리뷰트가 construct에 명시되어 있으면, true를 반환한다.

    2. 그렇지 않으면 construct를 원래 interface, interface mixin, 또는 namespace 정의의 construct로 설정한다.

  5. construct가 interface mixin일 경우:

    1. exposure condition 확장 어트리뷰트가 construct에 명시되어 있으면, true를 반환한다.

    2. 그렇지 않으면 construct를 H로 설정한다.

  6. 단언: construct는 interface, callback interface, 또는 namespace이다.

  7. exposure condition 확장 어트리뷰트가 construct에 명시되어 있으면, true를 반환한다.

  8. 그렇지 않으면 false를 반환한다.

참고: JavaScript 글로벌 객체의 관련 설정 객체가 시간이 지나도 보안 컨텍스트 또는 cross-origin isolated capability 여부가 바뀔 수 없으므로, 인터페이스 또는 인터페이스 멤버의 프로퍼티를 생성할지 결정하는 것은 초기 객체가 생성될 때 한 번만 이루어지면 됩니다.

자세한 요구사항은 § 3.7 인터페이스, § 3.7.5 상수, § 3.7.6 속성, § 3.7.7 연산 및 [Exposed] 사용 규칙을 참조하세요.

[Exposed]는 interface, callback interface, namespace, 또는 개별 interface member, mixin, namespace member가 워커, Worklet, Window, 또는 이들의 조합에서 사용 가능하도록 제어하는 데 사용됩니다.

다음 IDL 프래그먼트는 이를 어떻게 달성할 수 있는지 보여줍니다:

[Exposed=Window, Global=Window]
interface Window {
  // ...
};

// SharedWorkerGlobalScope와 DedicatedWorkerGlobalScope 모두에서 동일한 식별자 Worker를 사용하면,
// [Exposed] 확장 어트리뷰트에서 둘 다 한 번에 지정할 수 있습니다.
[Exposed=Worker, Global=Worker]
interface SharedWorkerGlobalScope : WorkerGlobalScope {
  // ...
};

[Exposed=Worker, Global=Worker]
interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
  // ...
};

// Dimensions는 워커와 메인 스레드 모두에서 사용 가능
[Exposed=(Window,Worker)]
interface Dimensions {
  constructor(double width, double height);
  readonly attribute double width;
  readonly attribute double height;
};

// WorkerNavigator는 워커에서만 사용 가능. 워커의 글로벌 스코프에서 WorkerNavigator를 평가하면 인터페이스 객체가 반환되고,
// 메인 스레드에서는 ReferenceError가 발생합니다.
[Exposed=Worker]
interface WorkerNavigator {
  // ...
};

// Node는 메인 스레드에서만 사용 가능. 워커의 글로벌 스코프에서 Node를 평가하면 ReferenceError가 발생합니다.
[Exposed=Window]
interface Node {
  // ...
};

// MathUtils는 워커와 메인 스레드 모두에서 사용 가능
[Exposed=(Window,Worker)]
namespace MathUtils {
  double someComplicatedFunction(double x, double y);
};

// WorkerUtils는 워커에서만 사용 가능. 워커의 글로벌 스코프에서 WorkerUtils를 평가하면 네임스페이스 객체가 반환되고,
// 메인 스레드에서는 ReferenceError가 발생합니다.
[Exposed=Worker]
namespace WorkerUtils {
  undefined setPriority(double x);
};

// NodeUtils는 메인 스레드에서만 사용 가능. 워커의 글로벌 스코프에서 NodeUtils를 평가하면 ReferenceError가 발생합니다.
[Exposed=Window]
namespace NodeUtils {
  DOMString getAllText(Node node);
};

3.3.8. [Global]

[Global] 확장 어트리뷰트가 interface에 나타나면, 해당 interface를 구현하는 객체가 realm의 글로벌 객체로 사용됨을 의미합니다.

[Global] 확장 어트리뷰트는 또한 해당 interface의 글로벌 이름(global names)을 정의합니다:

[Global] 확장 어트리뷰트가 식별자(identifier)를 가지는 경우

« 주어진 식별자 »

[Global] 확장 어트리뷰트가 식별자 리스트(identifier list)를 가지는 경우

식별자 리스트

[Global] 확장 어트리뷰트는 위의 형태 중 하나여야 합니다.

참고: 해당 interface의 글로벌 이름(global names)은 [Exposed] 확장 어트리뷰트에서 참조할 수 있는 식별자입니다. 하나의 이름이 여러 글로벌 인터페이스에서 공유될 수 있으므로, 하나의 인터페이스가 [Exposed]를 사용해서 여러 글로벌에 쉽게 노출될 수 있습니다. 예를 들어 "Worker"는 여러 스레드 관련 글로벌 인터페이스를 참조합니다.

이러한 글로벌 interface의 경우 프로토타입 체인 구조와 interface member에 해당하는 프로퍼티가 프로토타입 객체에 어떻게 반영되는지가 다른 인터페이스와 다릅니다. 구체적으로:

  1. 모든 이름있는 프로퍼티(named properties)는 프로토타입 체인 상의 객체(즉, named properties object)에 노출되며, 객체 자체에는 노출되지 않습니다.

  2. interface member들은 interface에서 객체 자체의 프로퍼티로 대응되며, interface prototype objects에는 대응되지 않습니다.

모든 realm은 글로벌 프로토타입 체인 변경 가능(is global prototype chain mutable) 불리언을 가지며, realm이 생성될 때 설정할 수 있습니다. 해당 값은 realm의 수명 동안 변경될 수 없습니다. 기본값은 false입니다.

이는 ShadowRealm 글로벌이 mutable 프로토타입을 가질 수 있게 합니다.

이름있는 프로퍼티(named properties)를 프로토타입 체인 객체에 배치하는 이유는 변수 선언 및 bareword 할당이 글로벌 객체의 프로퍼티로 이름있는 프로퍼티를 shadow하도록 하기 위함입니다.

interface member에 대응하는 프로퍼티를 객체 자체에 배치하면, 아래와 같은 feature detection 코드가 동작하게 됩니다:

var indexedDB = window.indexedDB || window.webkitIndexedDB ||
                window.mozIndexedDB || window.msIndexedDB;

var requestAnimationFrame = window.requestAnimationFrame ||
                            window.mozRequestAnimationFrame || ...;

JavaScript에서 변수 선언이 처리되는 방식 때문에, 위 코드는 window.indexedDB 및 window.requestAnimationFrame이 undefined로 평가됨을 의미합니다. 이는 shadowing 변수 프로퍼티가 할당 이전에 이미 생성되었기 때문입니다.

[Global] 확장 어트리뷰트가 interface에 사용된 경우:

[Global]이 partial interface 정의에 지정된 경우, 해당 partial interface 정의는 named property getter를 정의하는 부분이어야 합니다.

[Global] 확장 속성은 동일한 realm에서 둘 이상의 객체가 구현할 수 있는 인터페이스에 사용해서는 안 됩니다.

참고: 이는 named properties object가 프로토타입 체인에 위치하며, 여러 객체의 named properties가 해당 객체에서 모두 노출되는 것은 의미가 없기 때문입니다.

interface에 [Global] 확장 어트리뷰트가 선언된 경우, 해당 interface 전체에 걸쳐 동일한 식별자를 가진 member가 둘 이상 존재할 수 없습니다. 또한, 하나의 stringifier나 하나의 iterable 선언, async iterable 선언, maplike 선언, setlike 선언도 둘 이상 존재할 수 없습니다.

참고: interface의 모든 member는 해당 interface를 구현하는 객체에 모두 평탄화되어 할당되기 때문입니다.

자세한 요구사항은 § 3.7.4 이름있는 프로퍼티 객체(named properties object)에서 [Global] 사용 시 이름있는 프로퍼티 관련 규칙, § 3.7.5 상수, § 3.7.6 속성, § 3.7.7 연산에서 인터페이스 멤버에 대응하는 프로퍼티의 위치에 관한 요구사항을 참고하세요.

Window interface는 frame을 Window 객체의 프로퍼티로 노출합니다. Window 객체는 JavaScript 글로벌 객체 역할도 하므로, 변수 선언이나 이름있는 프로퍼티에 대한 할당은 해당 값으로 대체됩니다. attribute에 대해 변수를 선언하면 기존 프로퍼티가 대체되지 않습니다.

[Exposed=Window, Global=Window]
interface Window {
  getter any (DOMString name);
  attribute DOMString name;
  // ...
};

아래 HTML 문서는 Window 객체의 이름있는 프로퍼티가 shadow되는 방법과, attribute와 같은 이름의 변수 선언이 기존 프로퍼티를 대체하지 않는 방법을 보여줍니다:

<!DOCTYPE html>
<title>Variable declarations and assignments on Window</title>
<iframe name=abc></iframe>
<!-- Shadowing named properties -->
<script>
  window.abc;    // iframe의 Window 객체를 반환.
  abc = 1;       // 이름있는 프로퍼티를 shadow함.
  window.abc;    // 1을 반환.
</script>

<!-- IDL attribute 프로퍼티 보존 -->
<script>
  Window.prototype.def = 2;         // 프로토타입에 프로퍼티 추가.
  window.hasOwnProperty("length");  // true 반환.
  length;                           // 1 반환.
  def;                              // 2 반환.
</script>
<script>
  var length;                       // 변수 선언은 기존 프로퍼티를 대체하지 않음.
  length;                           // 1 반환.
  var def;                          // 변수 선언은 shadow 프로퍼티를 생성.
  def;                              // undefined 반환.
</script>

3.3.9. [NewObject]

[NewObject] 확장 어트리뷰트가 정규 또는 static operation에 나타나면, 해당 operation을 호출할 때 항상 새로 생성된 객체의 참조를 반환해야 함을 나타냅니다.

[NewObject] 확장 어트리뷰트는 인자를 가지지 않아야 합니다.

[NewObject] 확장 어트리뷰트는 정규 또는 static operation 중, 반환 타입이 interface 타입 또는 promise 타입인 것에만 사용할 수 있습니다.

예를 들어, 이 확장 어트리뷰트는 createElement() operation(Document interface의 메서드)에 적합합니다. 호출 시 항상 새 객체가 반환되기 때문입니다. [DOM]

[Exposed=Window]
interface Document : Node {
  [NewObject] Element createElement(DOMString localName);
  // ...
};

3.3.10. [PutForwards]

[PutForwards] 확장 어트리뷰트가 읽기 전용 정규 attribute 선언에, 해당 타입이 interface 타입일 때 나타나면, 해당 attribute에 값을 할당할 때 특정 동작을 하도록 합니다. 즉, 할당이 그 attribute가 참조하는 객체의 특정 attribute(확장 어트리뷰트 인자에 명시된)에 "전달"됩니다.

[PutForwards] 확장 어트리뷰트는 식별자를 가져야 합니다. 다음을 가정합니다:

이 경우, J에 attribute B가 존재해야 하며, 해당 식별자는 N 입니다. I를 구현하는 객체의 A에 값을 할당하면, 대신 A가 참조하는 객체의 B attribute에 값이 할당됩니다.

[PutForwards]-가 붙은 attribute는 체인(chained)이 가능합니다. 즉, [PutForwards] 확장 어트리뷰트가 붙은 attribute가 다시 같은 확장 어트리뷰트를 가진 attribute를 참조할 수 있습니다. 단, 전달된 할당 체인에 사이클이 있으면 안 됩니다. 사이클은 전달된 할당을 따라가다 특정 인터페이스의 attribute가 다시 나타나면 발생한 것입니다.

[PutForwards] 확장 어트리뷰트가 붙은 attribute는 [LegacyLenientSetter] 또는 [Replaceable] 확장 어트리뷰트와 함께 선언할 수 없습니다.

[PutForwards] 확장 어트리뷰트는 읽기 전용 attribute가 아닌 곳에 사용할 수 없습니다.

[PutForwards] 확장 어트리뷰트는 static attribute에 사용할 수 없습니다.

[PutForwards] 확장 어트리뷰트는 namespace에 선언된 attribute에 사용할 수 없습니다.

[PutForwards]의 구현 방법은 속성(Attributes) 절을 참고하세요.

다음 IDL 프래그먼트는 이름(Name)과 사람(Person) interface를 정의합니다. Person interface의 name attribute에 [PutForwards] 확장 어트리뷰트를 사용하여, 해당 attribute에 값을 할당하면 Person 객체의 full attribute에 값이 할당됨을 나타냅니다:

[Exposed=Window]
interface Name {
  attribute DOMString full;
  attribute DOMString family;
  attribute DOMString given;
};

[Exposed=Window]
interface Person {
  [PutForwards=full] readonly attribute Name name;
  attribute unsigned short age;
};

JavaScript 바인딩에서는 name 프로퍼티에 값을 할당할 수 있습니다:

var p = getPerson();           // Person 인스턴스 획득.

p.name = 'John Citizen';       // 이 문장...
p.name.full = 'John Citizen';  // ...이 문장과 동일한 동작.

3.3.11. [Replaceable]

[Replaceable] 확장 어트리뷰트가 읽기 전용 정규 attribute에 나타나면, 해당 플랫폼 객체에서 해당 프로퍼티를 할당하면 할당된 값으로 동일한 이름의 own property가 객체에 생성됩니다. 이 프로퍼티는 interface prototype object에 있는 accessor property를 shadow하게 됩니다.

[Replaceable] 확장 어트리뷰트는 인자를 가지지 않아야 합니다.

[Replaceable] 확장 어트리뷰트가 붙은 attribute는 [LegacyLenientSetter] 또는 [PutForwards] 확장 어트리뷰트와 함께 선언할 수 없습니다.

[Replaceable] 확장 어트리뷰트는 읽기 전용이 아닌 attribute에 사용할 수 없습니다.

[Replaceable] 확장 어트리뷰트는 static attribute에 사용할 수 없습니다.

[Replaceable] 확장 어트리뷰트는 namespace에 선언된 attribute에 사용할 수 없습니다.

구체적 요구사항은 § 3.7.6 속성에서 [Replaceable] 사용 규칙을 참고하세요.

다음 IDL 프래그먼트는 카운터를 증가시키는 operation과 0으로 초기화되는 카운터의 값을 노출하는 attribute를 가진 interface를 정의합니다:

[Exposed=Window]
interface Counter {
  [Replaceable] readonly attribute unsigned long value;
  undefined increment();
};

플랫폼 객체에서 value 프로퍼티에 값을 할당하면, 해당 attribute에 대응하는 프로퍼티를 shadow합니다:

var counter = getCounter();                              // Counter 인스턴스 획득.
counter.value;                                           // 0 반환.

counter.hasOwnProperty("value");                         // false 반환.
Object.getPrototypeOf(counter).hasOwnProperty("value");  // true 반환.

counter.increment();
counter.increment();
counter.value;                                           // 2 반환.

counter.value = 'a';                                     // Counter::value와는 무관한 값으로 shadow.
                                                         // 

counter.hasOwnProperty("value");                         // true 반환.

counter.increment();
counter.value;                                           // 'a' 반환.

delete counter.value;                                    // 원래 프로퍼티 복원.
counter.value;                                           // 3 반환.

3.3.12. [SameObject]

[SameObject] 확장 어트리뷰트가 읽기 전용 attribute에 나타나면, 해당 객체의 attribute 값을 얻을 때 항상 동일한 값을 반환해야 함을 나타냅니다.

[SameObject] 확장 어트리뷰트는 인자를 가지지 않아야 합니다.

[SameObject] 확장 어트리뷰트는 읽기 전용 attribute 중, 타입이 interface 타입 또는 object일 때만 사용할 수 있습니다.

예시로, 이 확장 어트리뷰트는 implementation attribute(Document interface의 속성)에 적합합니다. 해당 Document 객체에 대해 항상 동일한 객체가 반환되기 때문입니다. [DOM]

[Exposed=Window]
interface Document : Node {
  [SameObject] readonly attribute DOMImplementation implementation;
  // ...
};

3.3.13. [SecureContext]

[SecureContext] 확장 어트리뷰트가 interface, partial interface, interface mixin, partial interface mixin, callback interface, namespace, partial namespace, interface member, interface mixin member, 또는 namespace member에 나타나면, 해당 구성 요소가 노출되는 환경이 보안 컨텍스트(secure context)일 때만 노출됨을 나타냅니다. [SecureContext] 확장 어트리뷰트는 다른 구성 요소에 사용하면 안 됩니다.

[SecureContext] 확장 어트리뷰트는 인자를 가지지 않아야 합니다.

[SecureContext] 가 오버로드된 operation에 나타나면, 모든 오버로드에 반드시 나타나야 합니다.

[SecureContext] 확장 어트리뷰트는 다음 경우 모두에 명시될 수 없습니다:

참고: [SecureContext] 확장 어트리뷰트를 멤버에 추가해도 정의 전체에 이미 [SecureContext] 확장 어트리뷰트가 있으면 멤버의 노출 범위가 추가로 제한되지 않기 때문입니다.

[SecureContext] 확장 어트리뷰트가 없는 interface는 [SecureContext]를 명시한 다른 interface를 상속하면 안 됩니다.

[SecureContext] 는 [CrossOriginIsolated]에서 조건부 노출됨 상태인 구성 요소에는 명시할 수 없습니다. (모든 cross-origin isolated 환경은 항상 보안 컨텍스트이므로 중복입니다.)

다음 IDL 프래그먼트는 모든 컨텍스트에서 실행 가능한 operation 1개와, 보안 컨텍스트에서만 실행 가능한 operation 2개를 가진 interface를 정의합니다.

[Exposed=Window]
interface ExampleFeature {
  // 모든 컨텍스트에서 성공
  Promise <Result> calculateNotSoSecretResult();

  // 이 operation은 비보안 컨텍스트에 노출되지 않습니다. 해당 컨텍스트에서 ExampleFeature.prototype에 "calculateSecretResult" 속성이 없습니다.
  [SecureContext] Promise<Result> calculateSecretResult();

  // 마찬가지로 이 attribute도 비보안 컨텍스트에 노출되지 않으며,
  // ExampleFeature.prototype에 "secretBoolean" 속성이 없습니다.
  [SecureContext] readonly attribute boolean secretBoolean;
};

// HeartbeatSensor는 비보안 컨텍스트에 노출되지 않으며, 멤버도 노출되지 않습니다.
// 해당 컨텍스트에서 Window에 "HeartbeatSensor" 속성이 없습니다.
[Exposed=Window, SecureContext]
interface HeartbeatSensor {
  Promise<float> getHeartbeatsPerMinute();
};

// 아래 interface mixin 멤버는 비보안 컨텍스트에서는 노출되지 않습니다. 즉, 비보안 컨텍스트에서는 ExampleFeature.prototype에 "snap" 속성이 없습니다.
[SecureContext]
interface mixin Snapshotable {
  Promise<boolean> snap();
};
ExampleFeature includes Snapshotable;

// 반면, 아래 interface mixin 멤버는 호스트 interface에 [SecureContext] 확장 어트리뷰트가 없으면 비보안 컨텍스트에서도 노출됩니다.
// 즉, 비보안 컨텍스트에서는 ExampleFeature.prototype에 "log" 속성이 있습니다.
interface mixin Loggable {
  Promise<boolean> log();
};
ExampleFeature includes Loggable;

3.3.14. [Unscopable]

[Unscopable] 확장 어트리뷰트가 정규 attribute 또는 정규 operation에 나타나면, 해당 인터페이스의 멤버를 가진 객체가 해당 멤버의 프로퍼티명을 객체 환경 레코드의 base object에 포함하지 않게 됨을 의미합니다. 결과적으로 프로퍼티명과 동일한 식별자를 사용하는 경우 with 문에서 해당 프로퍼티가 해석되지 않습니다. 이는 프로퍼티명을 interface prototype object의 %Symbol.unscopables% 프로퍼티 값에 포함시켜 구현됩니다.

[Unscopable] 확장 어트리뷰트는 인자를 가지지 않아야 합니다.

[Unscopable] 확장 어트리뷰트는 정규 attribute 또는 정규 operation 외의 곳에 사용하면 안 됩니다.

[Unscopable] 확장 어트리뷰트는 namespace에 선언된 attribute에는 사용할 수 없습니다.

구체적인 요구사항은 § 3.7.3 인터페이스 프로토타입 객체에서 [Unscopable] 관련 규칙을 참고하세요.

예를 들어, 다음과 같이 IDL을 정의한 경우:

[Exposed=Window]
interface Thing {
  undefined f();
  [Unscopable] g();
};

f 프로퍼티는 with 문에서 식별자로 참조할 수 있지만, g 프로퍼티는 참조할 수 없습니다:

var thing = getThing();  // Thing 인스턴스
with (thing) {
  f;                     // Function 객체 반환.
  g;                     // ReferenceError 발생.
}

3.4. 레거시 확장 어트리뷰트

이 절에서는 확장 어트리뷰트 중, JavaScript 바인딩에 영향을 주는 여러 종류를 정의합니다. § 3.3 확장 어트리뷰트에 있는 것과 달리, 이들 어트리뷰트는 레거시 Web 플랫폼 기능 명세를 위해서만 존재합니다. 명세에서 사용하지 말고, 레거시 API의 동작을 명시할 필요가 있을 때만 사용해야 합니다.

이러한 확장 어트리뷰트 사용을 고려하는 편집자는 이슈를 등록 하여 논의하는 것이 권장됩니다.

3.4.1. [LegacyFactoryFunction]

이 기능 대신 인터페이스에 생성자 operation을 정의하세요.

[LegacyFactoryFunction] 확장 어트리뷰트가 interface에 나타나면, JavaScript 글로벌 객체에 지정된 이름의 프로퍼티가 생성되고, 그 값은 해당 인터페이스를 구현하는 객체를 생성할 수 있는 함수가 됩니다. 하나의 interface에 여러 [LegacyFactoryFunction] 확장 어트리뷰트가 나타날 수 있습니다.

[LegacyFactoryFunction] 확장 어트리뷰트는 named argument list를 가져야 합니다. "=" 뒤에 오는 identifier가 [LegacyFactoryFunction]의 식별자(identifier)입니다. interface에 나타난 각 [LegacyFactoryFunction] 확장 어트리뷰트마다, 해당 프로퍼티의 값인 생성자 함수에 인자를 전달하여 interface 구현 객체를 생성할 수 있는 방법이 제공됩니다.

식별자는 다른 interface의 [LegacyFactoryFunction] 확장 어트리뷰트에 사용된 것과 같으면 안 되며, 이 interface 또는 다른 interface의 [LegacyWindowAlias] 확장 어트리뷰트에 사용된 식별자와 같아도 안 됩니다. 또한 interface object가 있는 interface의 식별자와 같아도 안 되고, reserved identifier도 사용할 수 없습니다.

[LegacyFactoryFunction] 와 [Global] 확장 어트리뷰트는 같은 interface에 동시에 명시할 수 없습니다.

레거시 factory 함수의 구현 방법은 § 3.7.2 Legacy factory functions에서 자세히 설명합니다.

다음 IDL은 [LegacyFactoryFunction] 확장 어트리뷰트를 사용하는 interface를 정의합니다.

[Exposed=Window,
 LegacyFactoryFunction=Audio(DOMString src)]
interface HTMLAudioElement : HTMLMediaElement {
  // ...
};

이 interface를 지원하는 JavaScript 구현에서는 HTMLAudioElement 객체를 Audio 함수로 생성할 수 있습니다.

typeof Audio;                   // 'function' 반환.

var a2 = new Audio('a.flac');   // 인자 1개 생성자를 사용해 HTMLAudioElement 생성.
                                // 

레거시 동작으로, 이러한 factory 함수는 prototype 프로퍼티가 원래 interface의 prototype과 같습니다:

console.assert(Audio.prototype === HTMLAudioElement.prototype);

3.4.2. [LegacyLenientSetter]

[LegacyLenientSetter] 확장 어트리뷰트가 읽기 전용 정규 attribute에 나타나면, 해당 attribute의 accessor property에 no-op setter가 생성됩니다. 이로 인해 strict mode에서 잘못된 프로퍼티 할당이 예외 없이 무시됩니다.

실제 페이지에서는 저자가 IDL attribute를 polyfill하려고 프로퍼티에 할당하는 경우가 종종 있으나, 실제로는 해당 프로퍼티가 이미 존재하는 경우도 있습니다. strict mode에서는 예외가 발생하여 페이지가 깨질 수 있지만, [LegacyLenientSetter] 가 없으면 브라우저에서 해당 기능을 ship할 수 없게 될 수도 있습니다.

[LegacyLenientSetter] 확장 어트리뷰트는 인자를 가지지 않아야 합니다. 읽기 전용 정규 attribute 외의 곳에는 사용할 수 없습니다.

[LegacyLenientSetter] 확장 어트리뷰트가 붙은 attribute는 [PutForwards] 또는 [Replaceable] 확장 어트리뷰트와 함께 선언할 수 없습니다.

[LegacyLenientSetter] 확장 어트리뷰트는 namespace에 선언된 attribute에는 사용할 수 없습니다.

[LegacyLenientSetter]의 구현 방법은 속성(Attributes) 절을 참고하세요.

다음 IDL은 [LegacyLenientSetter] 확장 어트리뷰트를 사용하는 interface를 정의합니다.

[Exposed=Window]
interface Example {
  [LegacyLenientSetter] readonly attribute DOMString x;
  readonly attribute DOMString y;
};

이 인터페이스를 지원하는 JavaScript 구현에서는 x에 대응하는 accessor property에 setter가 존재하며, strict mode에서도 아무 동작을 하지 않습니다.

"use strict";

var example = getExample();  // Example 인스턴스 획득.

// strict mode에서도 setter는 no-op이므로 예외 없음.
example.x = 1;

// strict mode에서 setter 없으므로 TypeError 발생.
example.y = 1;

3.4.3. [LegacyLenientThis]

[LegacyLenientThis] 확장 어트리뷰트가 정규 attribute에 나타나면, 해당 attribute의 getter나 setter를 this 값이 해당 attribute가 선언된 interface를 구현하지 않는 객체로 호출하면, 아무 동작도 하지 않게 됩니다.

[LegacyLenientThis] 확장 어트리뷰트는 인자를 가지지 않아야 합니다. static attribute에는 사용할 수 없습니다.

[LegacyLenientThis] 확장 어트리뷰트는 namespace에 선언된 attribute에는 사용할 수 없습니다.

[LegacyLenientThis]의 구현 방법은 속성(Attributes) 절을 참고하세요.

다음 IDL은 [LegacyLenientThis] 확장 어트리뷰트를 사용하는 interface를 정의합니다.

[Exposed=Window]
interface Example {
  [LegacyLenientThis] attribute DOMString x;
  attribute DOMString y;
};

이 인터페이스를 지원하는 JavaScript 구현에서는 x에 대응하는 accessor property의 getter와 setter를 Example 객체가 아닌 객체로도 호출할 수 있습니다.

var example = getExample();  // Example 인스턴스 획득.
var obj = { };

// 정상 동작.
example.x;

// this 값이 Example 객체가 아니고 [LegacyLenientThis]가 사용되었으므로 무시됨.
Object.getOwnPropertyDescriptor(Example.prototype, "x").get.call(obj);

// Example.prototype도 Example 객체가 아니므로 무시됨.
Example.prototype.x;

// Example.prototype이 Example 객체가 아니므로 TypeError 발생.
Example.prototype.y;

3.4.4. [LegacyNamespace]

이 기능 대신, 인터페이스 이름을 특정 접두사로 시작하는 네이밍 컨벤션을 사용하여 식별자에 점 없이 작성하세요.

[LegacyNamespace] 확장 어트리뷰트가 interface에 나타나면, 해당 인터페이스 객체가 글로벌 객체의 프로퍼티로 생성되지 않고, 확장 어트리뷰트 인자로 지정된 namespace의 프로퍼티로 생성됨을 의미합니다.

[LegacyNamespace] 확장 어트리뷰트는 식별자를 가져야 하며, 해당 식별자는 namespace 정의의 식별자여야 합니다.

[LegacyNamespace] 와 [LegacyNoInterfaceObject] 확장 어트리뷰트는 같은 interface에 동시에 명시할 수 없습니다.

interface가 namespace에 어떻게 노출되는지에 대한 자세한 내용은 § 3.13.1 네임스페이스 객체를 참고하세요.

다음 IDL 프래그먼트는 namespace와 [LegacyNamespace]으로 정의된 interface를 보여줍니다.
namespace Foo { };

[LegacyNamespace=Foo]
interface Bar {
  constructor();
};

위 네임스페이스와 인터페이스를 지원하는 JavaScript 구현에서는, Bar 생성자를 다음과 같이 접근할 수 있습니다:

var instance = new Foo.Bar();

3.4.5. [LegacyNoInterfaceObject]

[LegacyNoInterfaceObject] 확장 어트리뷰트가 interface에 나타나면, 해당 인터페이스의 JavaScript 바인딩에서 interface object가 존재하지 않음을 의미합니다.

[LegacyNoInterfaceObject] 확장 어트리뷰트는 인자를 가지지 않아야 합니다.

[LegacyNoInterfaceObject] 확장 어트리뷰트는 해당 interface에 생성자나 static operation이 정의되어 있으면 사용할 수 없습니다.

[LegacyNoInterfaceObject] 확장 어트리뷰트가 명시되지 않은 interface는, [LegacyNoInterfaceObject] 확장 어트리뷰트가 명시된 interface를 상속하면 안 됩니다.

구체적 요구사항은 § 3.7 인터페이스에서 [LegacyNoInterfaceObject] 사용 규칙을 참고하세요.

다음 IDL 프래그먼트는 하나는 JavaScript 글로벌 객체에 인터페이스 객체가 노출되는 interface, 하나는 인터페이스 객체가 노출되지 않는 interface를 정의합니다:

[Exposed=Window]
interface Storage {
  undefined addEntry(unsigned long key, any value);
};

[Exposed=Window,
 LegacyNoInterfaceObject]
interface Query {
  any lookupEntry(unsigned long key);
};

위 IDL의 JavaScript 구현에서는 Storage의 프로토타입을 조작할 수 있지만, Query의 프로토타입은 조작할 수 없습니다.

typeof Storage;                        // "object" 반환

// Storage.addEntry에 alert() 트레이싱 추가
var fn = Storage.prototype.addEntry;
Storage.prototype.addEntry = function(key, value) {
  alert('Calling addEntry()');
  return fn.call(this, key, value);
};

typeof Query;                          // "undefined" 반환

var fn = Query.prototype.lookupEntry;  // 예외 발생, Query는 정의되지 않음

3.4.6. [LegacyNullToEmptyString]

[LegacyNullToEmptyString] 확장 속성이 DOMString 또는 USVString 타입에 나타나면, JavaScript null이 IDL 타입으로 변환될 때 기본 처리와 다르게 처리되도록 하는 새 IDL 타입을 만듭니다. 기본값인 "null"로 문자열화되는 대신 빈 문자열로 변환됩니다.

[LegacyNullToEmptyString] 확장 속성은 DOMString 또는 USVString이 아닌 타입과 연결되어서는 안 됩니다.

참고: 확장 속성 중 타입에 적용 가능한 다른 것들과 달리, [LegacyNullToEmptyString]은 DOMString?와 같은 널 허용 타입에는 사용할 수 없습니다. null이 이미 해당 타입의 유효한 값이기 때문입니다.

[LegacyNullToEmptyString]의 사용에 수반되는 구체적인 요구 사항은 § 3.2.10 DOMString을 참조하십시오.

다음 IDL 프래그먼트는 한 attribute의 타입과 한 operation의 인자 타입에 확장 어트리뷰트가 붙은 예시입니다:
[Exposed=Window]
interface Dog {
  attribute DOMString name;
  attribute [LegacyNullToEmptyString] DOMString owner;

  boolean isMemberOfBreed([LegacyNullToEmptyString] DOMString breedName);
};

이 Dog interface를 구현하는 JavaScript에서는, owner 프로퍼티에 null을 할당하거나, isMemberOfBreed 함수의 인자로 null을 전달하면 "null" 대신 빈 문자열로 처리됩니다:

var d = getDog();         // Dog 인터페이스를 구현하는 플랫폼 객체 d

d.name = null;            // .name 프로퍼티에 "null"이 할당됨.

d.owner = null;           // .owner 프로퍼티에 ""이 할당됨.

d.isMemberOfBreed(null);  // isMemberOfBreed 함수에 ""이 전달됨.

3.4.7. [LegacyOverrideBuiltIns]

[LegacyOverrideBuiltIns] 확장 속성이 인터페이스에 나타나면, 해당 인터페이스를 구현하는 레거시 플랫폼 객체에서 객체의 모든 지원되는 속성 이름에 해당하는 속성이 객체에 있는 것처럼 나타남을 나타냅니다. 객체 또는 그 프로토타입 체인에 어떤 다른 속성이 존재하는지와 관계없이 그렇습니다. 이는 명명된 속성이 항상 그렇지 않으면 객체에 나타날 모든 속성을 가리게 됨을 의미합니다. 이는 일반적인 동작과 대조되며, 일반적인 동작에서는 명명된 속성이 객체 자체 또는 그 프로토타입 체인의 어딘가에 같은 이름의 속성이 없는 경우에만 노출됩니다.

[LegacyOverrideBuiltIns] 확장 속성은 반드시 인수를 받지 않아야 하며 다음과 같은 인터페이스에는 나타나서는 안 됩니다. 명명된 속성 getter를 정의하지 않거나 [Global] 확장 속성으로도 선언된 인터페이스입니다. 확장 속성이 부분 인터페이스 정의에 지정된 경우, 해당 부분 인터페이스 정의는 반드시 인터페이스 정의에서 명명된 속성 getter를 정의하는 부분이어야 합니다.

[LegacyOverrideBuiltIns] 확장 어트리뷰트가 partial interface 정의에 명시되면, 해당 partial interface가 아닌 interface 전체에 명시된 것으로 간주합니다.

구체적 요구사항은 § 3.9 레거시 플랫폼 객체와 § 3.9.3 [[DefineOwnProperty]]에서 [LegacyOverrideBuiltIns] 사용 규칙을 참고하세요.

다음 IDL 프래그먼트는 하나는 named property getter가 있는 interface, 하나는 없는 interface를 정의합니다:

[Exposed=Window]
interface StringMap {
  readonly attribute unsigned long length;
  getter DOMString lookup(DOMString key);
};

[Exposed=Window,
 LegacyOverrideBuiltIns]
interface StringMap2 {
  readonly attribute unsigned long length;
  getter DOMString lookup(DOMString key);
};

위 두 인터페이스를 지원하는 JavaScript 구현에서는, 해당 인터페이스를 구현하는 객체에서 특정 프로퍼티를 얻으면 서로 다른 결과가 나옵니다:

// StringMap 인스턴스를 획득합니다. "abc", "length", "toString"이 지원되는 프로퍼티명이라고 가정합니다.
var map1 = getStringMap();

// named property getter를 호출합니다.
map1.abc;

// 객체의 "length" 프로퍼티를 가져오며, length attribute에 대응합니다.
map1.length;

// 객체의 프로토타입 체인에서 "toString" 프로퍼티를 가져옵니다.
map1.toString;

// StringMap2 인스턴스를 획득합니다. 역시 "abc", "length", "toString"이 지원됩니다.
var map2 = getStringMap2();

// named property getter를 호출합니다.
map2.abc;

// "length" 프로퍼티가 length attribute에 대응함에도 불구하고, 역시 named property getter를 호출합니다.
map2.length;

// "toString"이 map2의 프로토타입 체인에 있음에도 불구하고, 역시 named property getter를 호출합니다.
map2.toString;

3.4.8. [LegacyTreatNonObjectAsNull]

[LegacyTreatNonObjectAsNull] 확장 속성이 콜백 함수에 나타나면, 이는 타입이 널 허용 콜백 함수인 속성에 할당된 모든 값이 더 느슨하게 변환됨을 나타냅니다. 값이 객체가 아니면 null로 변환되고, 값이 호출 가능하지 않으면 호출되어도 아무 작업도 하지 않는 콜백 함수 값으로 변환됩니다.

§ 3.2.20 널 허용 타입 — T?, § 3.2.19 콜백 함수 타입 및 § 3.12 콜백 함수 호출을 참조하십시오. 이는 다음 사용에 수반되는 구체적인 요구 사항에 관한 것입니다: [LegacyTreatNonObjectAsNull] 입니다.

다음 IDL 조각은 하나의 속성을 가지는 인터페이스를 정의하며, 그 타입은 [LegacyTreatNonObjectAsNull]로 주석이 지정된 콜백 함수이고, 다른 하나의 타입은 콜백 함수이며 확장 속성이 없습니다:

callback OccurrenceHandler = undefined (DOMString details);

[LegacyTreatNonObjectAsNull]
callback ErrorHandler = undefined (DOMString details);

[Exposed=Window]
interface Manager {
  attribute OccurrenceHandler? handler1;
  attribute ErrorHandler? handler2;
};

JavaScript에서, 객체가 아닌 값(Number 등)이나 호출 가능(callable)이 아닌 값을 handler1에 할당하면 handler2에 할당할 때와 동작이 다릅니다:

var manager = getManager();  // Manager 인스턴스 획득

manager.handler1 = function() { };
manager.handler1;            // 함수 반환

try {
  manager.handler1 = 123;    // TypeError 발생
} catch (e) { }

try {
  manager.handler1 = {};     // TypeError 발생
} catch (e) { }

manager.handler2 = function() { };
manager.handler2;            // 함수 반환

manager.handler2 = 123;
manager.handler2;            // null 반환

manager.handler2 = {};
manager.handler2;            // 객체 반환

3.4.9. [LegacyUnenumerableNamedProperties]

[LegacyUnenumerableNamedProperties] 확장 속성이 인터페이스에 나타나고 해당 인터페이스가 명명된 속성을 지원하는 경우, 이는 인터페이스의 모든 명명된 속성이 열거 불가능함을 나타냅니다.

[LegacyUnenumerableNamedProperties] 확장 속성은 반드시 인수를 받지 않아야 하며 다음과 같은 인터페이스에는 나타나서는 안 됩니다. 명명된 속성 getter를 정의하지 않는 인터페이스입니다.

[LegacyUnenumerableNamedProperties] 확장 속성이 인터페이스에 지정된 경우, 이는 해당 인터페이스에서 파생된 모든 인터페이스에 적용되며 그 어느 인터페이스에도 지정되어서는 안 됩니다.

다음의 구체적인 요구 사항은 § 3.9.1 [[GetOwnProperty]]을 참조하십시오. 이는 다음 사용에 수반됩니다. [LegacyUnenumerableNamedProperties] 입니다.

3.4.10. [LegacyUnforgeable]

[LegacyUnforgeable] 확장 속성이 일반 속성 또는 비-정적 연산에 나타나면, 이는 해당 속성 또는 연산이 JavaScript 속성으로 반영되며 그 동작을 수정할 수 없고 객체에서 속성 조회를 수행하면 항상 해당 속성의 속성 값이 반환되는 방식임을 나타냅니다. 특히, 해당 속성은 구성 불가능하며 프로토타입이 아니라 객체 자체의 고유 속성으로 존재합니다.

속성 또는 연산은 주어진 인터페이스 A에서 위조 불가능하다고 합니다. 해당 속성 또는 연산이 A에 선언되어 있고, [LegacyUnforgeable] 확장 속성으로 주석이 지정된 경우입니다.

[LegacyUnforgeable] 확장 속성은 반드시 인수를 받지 않아야 합니다.

[LegacyUnforgeable] 확장 속성은 일반 속성 또는 비-정적 연산 이외에는 나타나서는 안 됩니다. 이것이 연산에 나타나는 경우, 해당 인터페이스에서 동일한 식별자를 가진 모든 연산에도 나타나야 합니다.

[LegacyUnforgeable] 확장 속성은 네임스페이스에 선언된 속성에는 사용해서는 안 됩니다.

속성 또는 연산 X가 인터페이스 A에서 위조 불가능하고, A가 다른 인터페이스 B의 상속된 인터페이스 중 하나라면, B에는 일반 속성 또는 비-정적 연산 중 X와 동일한 식별자를 가진 것이 있어서는 안 됩니다.

예를 들어, 아래와 같은 코드는 허용되지 않습니다:

[Exposed=Window]
interface A1 {
  [LegacyUnforgeable] readonly attribute DOMString x;
};
[Exposed=Window]
interface B1 : A1 {
  undefined x();  // 허용되지 않음; A1의 x에 의해 shadow됨.
};

[Exposed=Window]
interface B2 : A1 { };
B2 includes M1;
interface mixin M1 {
  undefined x();  // 허용되지 않음; B2의 x가 A1의 x에 의해 shadow됨.
};

구체적 요구사항은 § 3.7.6 속성, § 3.7.7 연산, § 3.8 인터페이스를 구현하는 플랫폼 객체, § 3.9 레거시 플랫폼 객체, § 3.9.3 [[DefineOwnProperty]]에서 [LegacyUnforgeable] 사용 규칙을 참고하세요.

다음 IDL 프래그먼트는 두 개의 attribute를 가진 interface를 정의하며, 그 중 하나는 [LegacyUnforgeable]로 지정되어 있습니다:

[Exposed=Window]
interface System {
  [LegacyUnforgeable] readonly attribute DOMString username;
  readonly attribute long long loginTime;
};

해당 interface를 지원하는 JavaScript 구현에서는 username attribute가 객체 자체의 non-configurable 프로퍼티로 노출됩니다:

var system = getSystem();                      // System 인스턴스 획득.

system.hasOwnProperty("username");             // true 반환
system.hasOwnProperty("loginTime");            // false 반환
System.prototype.hasOwnProperty("username");   // false 반환
System.prototype.hasOwnProperty("loginTime");  // true 반환

try {
  // 해당 프로퍼티가 non-configurable이므로 실패함.
  Object.defineProperty(system, "username", { value: "administrator" });
} catch (e) { }

// 아래 defineProperty는 성공 (System.prototype.loginTime은 configurable)
var forgedLoginTime = 5;
Object.defineProperty(System.prototype, "loginTime", { value: forgedLoginTime });

system.loginTime;  // forgedLoginTime 반환

3.4.11. [LegacyWindowAlias]

[LegacyWindowAlias] 확장 속성이 인터페이스에 나타나면, 이는 Window 인터페이스가 다음 각각에 대해 속성을 갖게 됨을 나타냅니다. 확장 속성에 언급된 각 식별자에 대해, 그 값은 해당 인터페이스의 인터페이스 객체입니다.

[LegacyWindowAlias] 확장 어트리뷰트는 식별자 또는 식별자 리스트를 가져야 합니다. “=” 이후에 나오는 식별자들은 [LegacyWindowAlias]의 식별자(identifier)입니다.

[LegacyWindowAlias]의 식별자들은 이 interface 또는 다른 interface의 [LegacyWindowAlias]에서 사용된 것과 같으면 안 되며, 이 interface 또는 다른 interface의 [LegacyFactoryFunction]에서 사용된 식별자와 같아도 안 되고, interface 객체가 있는 interface의 식별자와 같아도 안 되며, 예약된 식별자도 사용할 수 없습니다.

[LegacyWindowAlias]와 [LegacyNoInterfaceObject] 확장 어트리뷰트는 같은 interface에 동시에 명시할 수 없습니다.

[LegacyWindowAlias]와 [LegacyNamespace] 확장 어트리뷰트도 같은 interface에 명시할 수 없습니다.

[LegacyWindowAlias] 확장 어트리뷰트는 Window interface가 노출 집합에 포함되지 않은 interface에는 명시할 수 없습니다.

한 interface에 둘 이상의 [LegacyWindowAlias] 확장 어트리뷰트를 명시할 수 없습니다.

레거시 window alias의 구현 방법은 § 3.7 인터페이스에서 자세히 설명합니다.

다음 IDL은 [LegacyWindowAlias] 확장 어트리뷰트를 사용하는 interface를 정의합니다.

[Exposed=Window,
 LegacyWindowAlias=WebKitCSSMatrix]
interface DOMMatrix : DOMMatrixReadOnly {
  // ...
};

이 interface를 지원하는 JavaScript 구현에서는 Window 객체에 동일한 값을 가지는 두 개의 프로퍼티가 노출됩니다. 하나는 보통대로 interface 객체를 노출하고, 하나는 레거시 이름으로 노출합니다.

WebKitCSSMatrix === DOMMatrix;     // true 반환

var m = new WebKitCSSMatrix();     // DOMMatrix를 구현하는 새 객체 생성
                                   // 

m.constructor === DOMMatrix;       // true 반환
m.constructor === WebKitCSSMatrix; // true 반환
{}.toString.call(m);               // '[object DOMMatrix]' 반환

3.5. 보안(Security)

아래 절들에 정의된 특정 알고리즘은 주어진 객체에 보안 검사를 수행한다고 정의되어 있습니다. 이 검사는 주어진 operation 호출이나 attribute 접근이 허용되어야 하는지를 결정하는 데 사용됩니다. 보안 검사는 다음 세 입력값을 사용합니다:

  1. operation 호출이나 attribute 접근이 수행되는 플랫폼 객체

  2. 해당 operation 또는 attribute의 식별자

  3. 함수 객체(function object)의 타입 — "method"(IDL operation에 해당하는 경우), "getter"/"setter"(IDL attribute의 getter/setter 함수에 해당하는 경우)

참고: HTML 표준에서는 보안 검사 수행 방법을 정의합니다. [HTML]

3.6. 오버로드 해석 알고리즘

함수 호출이 해결되는 방식을 정의하기 위해, 오버로드 해결 알고리즘을 정의합니다. 입력은 유효 오버로드 집합, S와 JavaScript 값 목록 args입니다. 출력은 연산 또는 S의 항목 중 하나의 확장 속성과 IDL 값 목록 또는 특수 값 “missing”으로 구성된 쌍입니다. 알고리즘은 다음과 같이 동작합니다:

  1. maxarg를 S의 항목 중 가장 긴 타입 목록의 길이로 둡니다.

  2. n을 args의 크기로 둡니다.

  3. argcount를 min(maxarg, n)으로 초기화합니다.

  4. 타입 목록의 길이가 argcount가 아닌 모든 항목을 S에서 제거합니다.

  5. S가 비어 있으면, TypeError를 발생시킵니다.

  6. d를 −1로 초기화합니다.

  7. method를 undefined로 초기화합니다.

  8. S에 둘 이상의 항목이 있으면, d를 S의 항목에 대한 구별 인수 인덱스로 설정합니다.

  9. values를 빈 목록으로 초기화하며, 각 항목은 IDL 값 또는 특수 값 “missing” 중 하나가 됩니다.

  10. i를 0으로 초기화합니다.

  11. i < d인 동안:

    1. V를 args[i]로 둡니다.

    2. type을 S의 임의의 항목의 타입 목록에서 인덱스 i에 있는 타입으로 둡니다.

      참고: 이 시점에서 S의 모든 항목은 인덱스 i에서 동일한 타입과 선택성 값을 가집니다.

    3. optionality를 S의 임의의 항목의 선택성 값 목록에서 인덱스 i에 있는 값으로 둡니다.

    4. optionality가 “optional”이고 V가 undefined이면, 다음을 수행합니다:

      1. 인덱스 i의 인수가 기본값으로 선언되어 있으면, 해당 기본값을 values에 추가합니다.

      2. 그렇지 않으면, 특수 값 “missing”을 values에 추가합니다.

    5. 그렇지 않으면, V를 IDL 타입 type으로 변환한 결과를 values에 추가합니다.

    6. i를 i + 1로 설정합니다.

  12. i = d이면:

    1. V를 args[i]로 둡니다.

      참고: 이는 어떤 오버로드가 선택되는지 해결하는 데 사용될 인수입니다.

    2. V가 undefined이고, S에 선택성 값 목록의 인덱스 i에 “optional”이 있는 항목이 있다면, 다른 모든 항목을 S에서 제거합니다.

    3. 그렇지 않고: V가 null 또는 undefined이고, S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    4. 그렇지 않고: V가 플랫폼 객체이고, S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    5. 그렇지 않고: V가 Object이고, V에 [[ArrayBufferData]] 내부 슬롯이 있으며, S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    6. 그렇지 않고: V가 Object이고, V에 [[DataView]] 내부 슬롯이 있으며, S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    7. 그렇지 않고: V가 Object이고, V에 [[TypedArrayName]] 내부 슬롯이 있으며, S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    8. 그렇지 않고: IsCallable(V)가 true이고, S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    9. 그렇지 않고: V가 Object이고 S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      그리고 다음이 모두 참인 것은 아니며,

      그리고 다음 단계를 수행한 후,

      1. method를 ? GetMethod(V, %Symbol.asyncIterator%)로 둡니다.

      2. method가 undefined이면, method를 ? GetMethod(V, %Symbol.iterator%)로 설정합니다.

      method가 undefined가 아니면, 다른 모든 항목을 S에서 제거합니다.

    10. 그렇지 않고: V가 Object이고 S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      그리고 다음 단계를 수행한 후,

      1. method를 ? GetMethod(V, %Symbol.iterator%)로 둡니다.

      method가 undefined가 아니면, 다른 모든 항목을 S에서 제거합니다.

    11. 그렇지 않고: V가 Object이고 S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    12. 그렇지 않고: V가 Boolean이고 S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    13. 그렇지 않고: V가 Number이고 S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    14. 그렇지 않고: V가 BigInt이고 S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    15. 그렇지 않고: S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    16. 그렇지 않고: S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    17. 그렇지 않고: S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    18. 그렇지 않고: S에 타입 목록의 위치 i에 다음 타입 중 하나가 있는 항목이 있다면,

      다른 모든 항목을 S에서 제거합니다.

    19. 그렇지 않고: S에 타입 목록의 위치 i에 any가 있는 항목이 있으면, 다른 모든 항목을 S에서 제거합니다.

    20. 그렇지 않으면: TypeError를 발생시킵니다.

  13. callable을 S의 유일한 항목의 연산 또는 확장 속성으로 둡니다.

  14. i = d이고 method가 undefined가 아니면:

    1. V를 args[i]로 둡니다.

    2. T를 S에 남은 항목의 타입 목록에서 인덱스 i에 있는 타입으로 둡니다.

    3. 단언: T는 시퀀스 타입입니다.

    4. V와 method로부터 타입 T의 시퀀스를 생성한 결과를 values에 추가합니다.

    5. i를 i + 1로 설정합니다.

  15. i < argcount인 동안:

    1. V를 args[i]로 둡니다.

    2. type을 S에 남은 항목의 타입 목록에서 인덱스 i에 있는 타입으로 둡니다.

    3. optionality를 S에 남은 항목의 선택성 값 목록에서 인덱스 i에 있는 값으로 둡니다.

    4. optionality가 “optional”이고 V가 undefined이면, 다음을 수행합니다:

      1. 인덱스 i의 인수가 기본값으로 선언되어 있으면, 해당 기본값을 values에 추가합니다.

      2. 그렇지 않으면, 특수 값 “missing”을 values에 추가합니다.

    5. 그렇지 않으면, V를 IDL 타입 type으로 변환한 결과를 values에 추가합니다.

    6. i를 i + 1로 설정합니다.

  16. i가 callable이 받도록 선언된 인수의 수보다 작은 동안:

    1. callable의 인덱스 i에 있는 인수가 기본값으로 선언되어 있으면, 해당 기본값을 values에 추가합니다.

    2. 그렇지 않고, callable의 인덱스 i에 있는 인수가 가변 인수가 아니면, 특수 값 “missing”을 values에 추가합니다.

    3. i를 i + 1로 설정합니다.

  17. <callable, values> 쌍을 반환합니다.

오버로드 해석 알고리즘은 어떤 오버로드된 operation, 생성자 등이 호출되는지 식별하는 것과, JavaScript 인자 값을 해당하는 IDL 값으로 변환하는 두 작업을 수행합니다. 비공식적으로 작동 방식은 다음과 같습니다.

먼저, 유효한 오버로드를 선택하는 과정은 함수에 전달된 JavaScript 인자 개수를 고려하여 진행됩니다:

올바른 인자 개수의 오버로드 집합을 얻은 후에는, JavaScript 값들을 왼쪽부터 오른쪽으로 변환합니다. 오버로드 제약의 성질 덕분에, 이 시점에 오버로드가 여러 개 남아 있다면, 인자 리스트 중 한 위치에서 최종적으로 어떤 오버로드를 선택할지 구분하게 됩니다. 이 위치가 구분 인자 인덱스(distinguishing argument index)입니다.

먼저 구분 인자 왼쪽의 인자들을 변환합니다.(구분 인자 인덱스 왼쪽에 위치한 인자는 모든 오버로드에서 같은 타입이어야 합니다.) 그 다음, 구분 인자 인덱스에 전달된 JavaScript 값의 타입을 검사하여 어떤 IDL 타입에 대응될 수 있는지 결정합니다. 이를 통해 최종적으로 호출할 오버로드를 선택합니다. 만약 전달된 값이 undefined이고 해당 위치가 optional 인자라면, 해당 오버로드를 선택합니다. 전달된 값 타입에 맞는 유효한 오버로드가 없다면 TypeError가 발생합니다. 일반적으로, 구분 인자 인덱스의 값 검사에는 부작용이 없으며, 오버로드 해석 알고리즘에서 발생하는 유일한 부작용은 JavaScript 값을 IDL 값으로 변환하는 과정에만 있습니다. (예외적으로, 어떤 오버로드가 구분 인자 인덱스에 async sequence 타입, sequence 타입, 또는 frozen array 타입을 가지는 경우가 있습니다. 이때는 %Symbol.asyncIterator% / %Symbol.iterator% 프로퍼티를 얻어 적합한 오버로드를 결정하며, 구분 인자에 대한 변환은 따로 수행한 뒤 다음 단계를 계속 진행합니다.)

이제 사용할 오버로드가 결정되었습니다. 남은 인자들은 구분 인자부터 오른쪽으로 변환하며, 앞서 초과되어 무시된 인자들은 계속 무시합니다.

optional 인자의 JavaScript 값을 해당 IDL 값으로 변환할 때, undefined는 optional 인자의 기본값이 있으면 그 값으로, 없으면 특수값 “missing”으로 변환됩니다.

마지막 가변 인자(variadic argument)에 해당하는 optional 인자에서는 undefined가 “missing”으로 특별하게 취급되지 않습니다. undefined 값은 가변 인자 타입으로, optional이 아닌 인자와 동일하게 변환됩니다.

3.7. 인터페이스

주어진 realm에서 노출되며 [LegacyNoInterfaceObject] 또는 [LegacyNamespace] 확장 속성으로 선언되지 않은 모든 인터페이스에 대해, 해당 realm의 전역 객체에 대응하는 속성이 존재합니다. 해당 속성의 이름은 인터페이스의 식별자이며, 그 값은 인터페이스 객체라고 하는 객체입니다. 인터페이스 객체의 특성은 § 3.7.1 인터페이스 객체에 설명되어 있습니다.

[LegacyWindowAlias] 확장 어트리뷰트가 노출된 인터페이스에 지정되어 있으면, [LegacyWindowAlias]의 각 식별자들에 포함된 각 식별자에 대해, Window 글로벌 객체에 대응하는 프로퍼티가 존재합니다. 프로퍼티 이름은 주어진 식별자이고, 값은 해당 인터페이스의 인터페이스 객체 참조입니다.

또한, 노출된 인터페이스에 [LegacyFactoryFunction] 확장 어트리뷰트가 있다면, 자바스크립트 글로벌 객체에 대응하는 프로퍼티가 존재합니다. 프로퍼티 이름은 [LegacyFactoryFunction]의 식별자이고, 값은 레거시 팩토리 함수(legacy factory function)이며, 해당 인터페이스를 구현하는 객체를 생성할 수 있도록 합니다. 레거시 팩토리 함수의 특성은 § 3.7.2 레거시 팩토리 함수에서 설명합니다.

이 절에서 정의된 몇몇 자바스크립트 메서드는 초기에 구현 객체 체크(implementation check)를 수행하여, 올바른 종류의 객체에서 호출되는지와 현재 컨텍스트에서 메서드 호출이 유효한지 확인합니다.

jsValue를 interface 인터페이스에 대해, name 식별자와 type 타입으로 구현 객체 체크(implementation-check an object)하는 절차:

  1. object를 ? ToObject(jsValue)로 한다.

  2. object가 플랫폼 객체(platform object)라면, 보안 검사(perform a security check)를 다음과 같이 수행한다:

    • 플랫폼 객체 object

    • 식별자 name

    • 타입 type

  3. object가 interface를 구현(implement)하지 않으면 throw TypeError를 발생시킨다.

  4. object를 반환한다.

이 알고리즘은 아직 모든 곳에서 일관되게 사용되고 있지 않습니다.

3.7.1. 인터페이스 객체

주어진 인터페이스 객체는 인터페이스에 대한 내장 함수 객체(built-in function object)입니다. 해당 객체는 상수 및 static 연산에 대응하는 프로퍼티를 가지며, 이에 대한 자세한 내용은 § 3.7.5 상수와 § 3.7.7 연산에서 설명합니다.

해당 인터페이스가 생성자 연산(constructor operation)으로 선언된 경우, 인터페이스 객체를 생성자(constructor)로 호출하여 해당 인터페이스를 구현하는 객체를 생성할 수 있습니다. 인터페이스 객체를 함수로 호출하면 예외가 발생합니다.

인터페이스 객체의 인터페이스가 생성자 연산으로 선언되지 않은 경우, 함수로 호출하거나 생성자로 호출하면 예외가 발생합니다.

인터페이스 객체는 인터페이스에 대한 인터페이스 프로토타입 객체라는 연관 객체를 가집니다. 이 객체는 인터페이스에 정의된 정규 attribute 및 정규 연산에 대응하는 프로퍼티를 가지며, § 3.7.3 인터페이스 프로토타입 객체에서 자세히 설명합니다.

참고: 인터페이스 객체는 함수 객체(function object)이므로, typeof 연산자를 적용하면 "function"을 반환합니다.

인터페이스는 생성자 재정의 단계(overridden constructor steps)를 가질 수 있으며, 인터페이스 객체가 호출되거나 생성될 때 동작을 변경할 수 있습니다. 기본적으로 인터페이스는 이러한 단계를 갖지 않습니다.

일반적으로 생성자는 생성자 연산 및 그 동작을 정의하여 설명합니다. 생성자 재정의 단계는 더 복잡한 상황에서만 사용해야 합니다. 이 기능을 사용하려는 편집자는 이슈를 등록하여 논의하는 것이 권장됩니다.

주어진 인터페이스 I에 대한 인터페이스 객체, id 식별자와 realm에서의 생성은 다음과 같이 생성(create an interface object)된다:

  1. steps를 I의 재정의된 생성자 단계가 존재한다면 그 값으로, 그렇지 않다면 다음 단계들로 둔다:

    1. I가 생성자 연산자로 선언되지 않았다면, 예외를 발생시킨다(throw) TypeError.

    2. NewTarget 이 undefined라면, 예외를 발생시킨다(throw) TypeError.

    3. args를 전달받은 인수들로 둔다.

    4. n을 args의 크기로 둔다.

    5. id를 인터페이스 I의 식별자(identifier)로 둔다.

    6. 생성자에 대해 효과적인 오버로드 집합을 계산하라. 식별자 id와 인터페이스 I, 인수 개수 n을 이용하여 계산하고, 결과를 S로 둔다.

    7. <constructor, values>를 오버로드 해결 알고리즘에 S와 args를 전달하여 얻은 결과로 둔다.

    8. object를 인터페이스를 구현하는 새 객체를 내부적으로 생성한 결과로 둔다. I, realm, 그리고 NewTarget을 인자로 사용한다.

    9. constructor의 생성자 단계를 object를 this로, values를 인자값으로 하여 수행한다.

    10. O를 object를 JavaScript 값으로 변환한 값으로 둔다.

    11. 단언: O는 I를 구현하는 객체다.

    12. 단언: O.[[Realm]]은 realm이다.

    13. O를 반환한다.

  2. constructorProto를 realm.[[Intrinsics]].[[%Function.prototype%]] 값으로 둔다.

  3. I가 다른 인터페이스 P로부터 상속받았다면, constructorProto를 realm에서 P의 인터페이스 객체로 설정한다.

  4. unforgeables를 OrdinaryObjectCreate(null)의 결과로 둔다.

  5. I의 위조 불가능한 정규 연산을 unforgeables에, realm을 참고하여 정의한다.

  6. I의 위조 불가능한 정규 속성을 unforgeables에, realm을 참고하여 정의한다.

  7. F.[[Unforgeables]]를 unforgeables로 설정한다.

    참고: 이 객체는 사용자 코드에 노출되지 않는다. 이는 오직 인터페이스의 위조 불가능한 멤버를 가진 모든 인스턴스가 속성 getter, 속성 setter, 연산 함수에 대해 동일한 JavaScript 함수 객체를 사용하도록 하기 위해 존재한다.

  8. length를 0으로 둔다.

  9. I가 생성자 연산자로 선언되었다면,

    1. 생성자에 대해 효과적인 오버로드 집합을 계산하라. 식별자 id, 인터페이스 I, 인수 개수 0을 사용한다. 결과를 S로 둔다.

    2. length를 S의 엔트리들 중 가장 짧은 인수 목록의 길이로 설정한다.

  10. F를 CreateBuiltinFunction(steps, length, id, « [[Unforgeables]] », realm, constructorProto) 결과로 둔다.

  11. proto를 인터페이스 프로토타입 객체 생성 결과로 둔다. 인터페이스 I와 realm을 사용한다.

  12. ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: proto, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false})를 수행한다.

  13. 상수 정의를 인터페이스 I와 F, realm에 대해 수행한다.

  14. 정적 속성 정의를 인터페이스 I, F, realm에 대해 수행한다.

  15. 정적 연산 정의를 인터페이스 I, F, realm에 대해 수행한다.

  16. F를 반환한다.

3.7.2. 레거시 팩토리 함수

어떤 레거시 팩터리 함수는 하나 이상의 [LegacyFactoryFunction] 확장 속성으로 인해 존재하며 주어진 식별자를 가진 내장 함수 객체입니다. 이를 통해 객체를 생성할 수 있으며, 해당 객체는 다음 [LegacyFactoryFunction] 확장 속성이 나타나는 인터페이스를 구현합니다.

레거시 팩터리 함수 중 식별자가 id이고 주어진 인터페이스 I에 대해 Realm realm에 있는 것은 다음과 같이 생성됩니다:

  1. steps를 다음 단계로 둡니다:

    1. NewTarget 가 undefined인 경우, 발생시킬 예외는 TypeError입니다.

    2. args를 전달된 인수로 둡니다.

    3. n을 크기인 args의 값으로 둡니다.

    4. 유효 오버로드 집합을 계산합니다. 다음 레거시 팩터리 함수에 대해 식별자 id를 가지며 인터페이스 I에 있고 인수 수가 n인 경우입니다. 그 결과를 S로 둡니다.

    5. <constructor, values>를 다음 전달의 결과로 둡니다. S와 args를 오버로드 해결 알고리즘에 전달합니다.

    6. object를 내부적으로 I를 구현하는 새 객체를 생성한 결과로 둡니다. 이때 realm과 NewTarget을 사용합니다.

    7. constructor의 생성자 단계를 수행합니다. object를 this로, values를 인수 값으로 사용합니다.

    8. O를 object를 JavaScript 값으로 변환한 것으로 둡니다.

    9. 단언: O는 구현 대상이 I인 객체입니다.

    10. 단언: O.[[Realm]]은 realm입니다.

    11. O를 반환합니다.

  2. 유효 오버로드 집합을 계산합니다. 다음 레거시 팩터리 함수에 대해 식별자 id를 가지며 인터페이스 I에 있고 인수 수가 0인 경우입니다. 그 결과를 S로 둡니다.

  3. length를 S의 항목 중 가장 짧은 인수 목록의 길이로 둡니다.

  4. F를 CreateBuiltinFunction(steps, length, id, « », realm)으로 둡니다.

  5. proto를 인터페이스 프로토타입 객체로 둡니다. 이 객체는 인터페이스 I의 realm 내 객체입니다.

  6. 다음을 수행합니다: ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: proto, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false}).

  7. F를 반환합니다.

3.7.3. 인터페이스 프로토타입 객체

정의된 모든 인터페이스에는 인터페이스 프로토타입 객체가 존재하며, 인터페이스가 [LegacyNoInterfaceObject] 확장 속성으로 선언되었는지 여부와 관계없습니다.

주어진 인터페이스 프로토타입 객체는 인터페이스 interface와 Realm realm에 대해 다음과 같이 생성됩니다:

  1. proto를 null로 둡니다.

  2. interface가 [Global] 확장 속성으로 선언되어 있고, interface가 명명된 속성을 지원하면, proto를 interface와 realm에 대해 명명된 속성 객체를 생성한 결과로 설정합니다.

  3. 그렇지 않고, interface가 다른 인터페이스에서 상속하도록 선언된 경우, proto를 realm에 있는 해당 인터페이스 프로토타입 객체로 설정합니다. 이는 해당 상속된 인터페이스의 것입니다.

  4. 그렇지 않고, interface가 DOMException 인터페이스인 경우, proto를 realm.[[Intrinsics]].[[%Error.prototype%]]로 설정합니다.

  5. 그렇지 않으면, proto를 realm.[[Intrinsics]].[[%Object.prototype%]]로 설정합니다.

  6. 단언: proto는 Object입니다.

  7. interfaceProtoObj를 null로 둡니다.

  8. realm의 전역 프로토타입 체인이 변경 가능한지 여부가 true이면:

    1. interfaceProtoObj를 OrdinaryObjectCreate(proto)로 설정합니다.

  9. 그렇지 않고, interface가 [Global] 확장 속성으로 선언되어 있거나, interface가 [Global] 확장 속성으로 선언된 인터페이스의 상속된 인터페이스 집합에 포함되어 있다면:

    1. interfaceProtoObj를 MakeBasicObject(« [[Prototype]], [[Extensible]] »)로 설정합니다.

    2. interfaceProtoObj.[[Prototype]]을 proto로 설정합니다.

    3. 불변 프로토타입 특수 객체에 고유한 interfaceProtoObj의 내부 메서드를 다음에 지정된 정의로 설정합니다: ECMA-262 불변 프로토타입 특수 객체.

  10. 그렇지 않으면, interfaceProtoObj를 OrdinaryObjectCreate(proto)로 설정합니다.

  11. interface에 [Unscopable] 확장 속성으로 선언된 멤버가 하나라도 있다면, 다음을 수행합니다:

    1. unscopableObject를 OrdinaryObjectCreate(null)로 둡니다.

    2. interface의 [Unscopable] 확장 속성으로 선언된 각 노출된 멤버 member에 대해:

      1. id를 member의 식별자로 둡니다.

      2. ! CreateDataPropertyOrThrow(unscopableObject, id, true)를 수행합니다.

    3. desc를 PropertyDescriptor{[[Value]]: unscopableObject, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}로 둡니다.

    4. ! DefinePropertyOrThrow(interfaceProtoObj, %Symbol.unscopables%, desc)를 수행합니다.

  12. interface가 [Global] 확장 속성으로 선언되지 않았다면:

    1. 주어진 realm에 대해 interfaceProtoObj에 interface의 일반 속성을 정의합니다.

    2. 주어진 realm에 대해 interfaceProtoObj에 interface의 일반 연산을 정의합니다.

    3. 주어진 realm에 대해 interfaceProtoObj에 interface의 반복 메서드를 정의합니다.

    4. 주어진 realm에 대해 interfaceProtoObj에 interface의 비동기 반복 메서드를 정의합니다.

  13. 주어진 realm에 대해 interfaceProtoObj에 interface의 상수를 정의합니다.

  14. [LegacyNoInterfaceObject] 확장 속성이 interface에 지정되지 않았다면:

    1. constructor를 realm에 있는 interface의 인터페이스 객체로 둡니다.

    2. desc를 PropertyDescriptor{[[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true, [[Value]]: constructor}로 둡니다.

    3. ! DefinePropertyOrThrow(interfaceProtoObj, "constructor", desc)를 수행합니다.

  15. interfaceProtoObj를 반환합니다.

또한, 인터페이스 프로토타입 객체는 다음에서 선언적으로 속성을 얻습니다:

대신 이러한 속성을 명령형으로 정의합니다.

[LegacyNoInterfaceObject] 확장 속성으로 정의된 인터페이스의 인터페이스 프로토타입 객체는 접근할 수 있습니다. 예를 들어, 다음 IDL이 있는 경우:

[Exposed=Window,
 LegacyNoInterfaceObject]
interface Foo {
};

partial interface Window {
  attribute Foo foo;
};

인터페이스 객체를 통해 인터페이스 프로토타입 객체에 접근할 수는 없습니다. (window.Foo로 존재하지 않기 때문입니다). 그러나 Foo 인스턴스는 [[GetPrototypeOf]] 내부 메서드를 호출하여 인터페이스 프로토타입 객체를 노출할 수 있습니다. 이 예에서는 Object.getPrototypeOf(window.foo)입니다.

인터페이스 프로토타입 객체의 클래스 문자열은 인터페이스의 정규화된 이름입니다.

3.7.4. 이름있는 프로퍼티 객체

다음과 같이 선언된 모든 인터페이스에 대해 [Global] 확장 속성으로 선언되고 명명된 속성을 지원하는 경우, 해당 인터페이스에는 명명된 속성 객체라는 객체가 존재하며 이 객체에서 명명된 속성이 노출됩니다.

주어진 인터페이스 interface와 realm realm에서 이름있는 프로퍼티 객체는 다음과 같이 생성(create a named properties object)된다:
  1. proto를 null로 한다.

  2. interface가 다른 인터페이스를 상속하면, proto를 상속된 인터페이스에 대한 해당 realm에서의 인터페이스 프로토타입 객체로 한다.

  3. 그렇지 않으면 proto를 realm.[[Intrinsics]].[[%Object.prototype%]]로 한다.

  4. obj를 MakeBasicObject(« [[Prototype]], [[Extensible]] »)로 한다.

  5. obj.[[GetOwnProperty]]를 § 3.7.4.1 [[GetOwnProperty]]에 명시된 대로 설정한다.

  6. obj.[[DefineOwnProperty]]를 § 3.7.4.2 [[DefineOwnProperty]]에 명시된 대로 설정한다.

  7. obj.[[Delete]]를 § 3.7.4.3 [[Delete]]에 명시된 대로 설정한다.

  8. obj.[[SetPrototypeOf]]를 § 3.7.4.4 [[SetPrototypeOf]]에 명시된 대로 설정한다.

  9. obj.[[PreventExtensions]]를 § 3.7.4.5 [[PreventExtensions]]에 명시된 대로 설정한다.

  10. obj.[[Prototype]]에 proto를 설정한다.

  11. obj를 반환한다.

참고: 이름있는 프로퍼티 객체의 [[OwnPropertyKeys]] 내부 메서드는 OrdinaryOwnPropertyKeys를 계속 사용합니다. 이는 레거시 플랫폼 객체와 다릅니다. 이름있는 프로퍼티는 “실제” own property가 아니므로 이 내부 메서드에서는 반환되지 않습니다.

이름있는 프로퍼티 객체의 클래스 문자열(class string)은 인터페이스의 식별자와 문자열 "Properties"를 연결한 값입니다.

3.7.4.1. [[GetOwnProperty]]

명명된 속성 객체 O의 [[GetOwnProperty]] 내부 메서드가 속성 키 P로 호출되면, 다음 단계를 수행합니다:

  1. A를 명명된 속성 객체 O에 대한 인터페이스로 둡니다.

  2. object를 O.[[Realm]]의 전역 객체로 둡니다.

  3. 단언: object는 A를 구현합니다.

  4. 속성 이름 P와 객체 object를 사용하여 명명된 속성 가시성 알고리즘을 실행한 결과가 true이면:

    1. operation을 명명된 속성 getter를 선언하는 데 사용된 연산으로 둡니다.

    2. value를 초기화되지 않은 변수로 둡니다.

    3. operation이 식별자 없이 정의되었다면, value를 인터페이스 설명에 나열된 단계를 수행한 결과로 설정하여 명명된 속성의 값을 결정합니다. 이때 P를 이름으로 사용합니다.

    4. 그렇지 않으면, operation은 식별자와 함께 정의되었습니다. value를 operation의 설명에 나열된 단계를 수행한 결과로 설정하며, P를 유일한 인수 값으로 사용합니다.

    5. desc를 필드가 없는 새로 생성된 속성 설명자로 둡니다.

    6. desc.[[Value]]를 value를 JavaScript 값으로 변환한 결과로 설정합니다.

    7. A가 [LegacyUnenumerableNamedProperties] 확장 속성이 있는 인터페이스를 구현한다면, desc.[[Enumerable]]을 false로 설정하고, 그렇지 않으면 true로 설정합니다.

    8. desc.[[Writable]]을 true로 설정하고 desc.[[Configurable]]을 true로 설정합니다.

    9. desc를 반환합니다.

  5. OrdinaryGetOwnProperty(O, P)를 반환합니다.

3.7.4.2. [[DefineOwnProperty]]

이름있는 프로퍼티 객체의 [[DefineOwnProperty]] 내부 메서드가 호출될 때, 다음 단계가 수행됩니다:

  1. false를 반환한다.

3.7.4.3. [[Delete]]

이름있는 프로퍼티 객체의 [[Delete]] 내부 메서드가 호출될 때, 다음 단계가 수행됩니다:

  1. false를 반환한다.

3.7.4.4. [[SetPrototypeOf]]

이름있는 프로퍼티 객체 O의 [[SetPrototypeOf]] 내부 메서드가 JavaScript 값 V로 호출될 때, 다음 단계가 수행된다:

  1. 만약 O의 연관 realm의 글로벌 프로토타입 체인이 mutable라면, ? OrdinarySetPrototypeOf(O, V)를 반환한다.

  2. ? SetImmutablePrototype(O, V)를 반환한다.

3.7.4.5. [[PreventExtensions]]

이름있는 프로퍼티 객체의 [[PreventExtensions]] 내부 메서드가 호출될 때, 다음 단계가 수행된다:

  1. false를 반환한다.

참고: 이렇게 하면 [[PreventExtensions]]가 실패하면서 이름있는 프로퍼티 객체가 확장 가능(extensible)하게 유지됩니다.

3.7.5. 상수

상수는 인터페이스 객체, 레거시 콜백 인터페이스 객체, 인터페이스 프로토타입 객체 및 인터페이스가 [Global] 확장 속성으로 선언된 경우, 해당 인터페이스를 구현하는 단일 객체에 노출됩니다.

상수를 정의한다: 인터페이스, 콜백 인터페이스 또는 네임스페이스 definition을 target에 대해, realm realm이 주어졌을 때, 아래 단계를 수행합니다:
  1. 각각의 상수 const에 대해, 멤버가 definition에 속한 경우:

    1. const가 realm에서 노출되지 않았다면, 계속합니다.

    2. value를 IDL 값을 자바스크립트 값으로 변환한 결과로 설정합니다.

    3. desc를 PropertyDescriptor{[[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false, [[Value]]: value}로 설정합니다.

    4. id를 const의 식별자로 설정합니다.

    5. ! DefinePropertyOrThrow(target, id, desc)를 수행합니다.

3.7.6. 속성

정적 속성은 다음에 노출됩니다 인터페이스 객체. 일반 속성은 다음에 노출됩니다 인터페이스 프로토타입 객체, 속성이 위조 불가능하거나 인터페이스가 [Global] 확장 속성으로 선언된 경우를 제외하며, 이 경우 해당 인터페이스를 구현하는 모든 객체에 노출됩니다.

일반 속성 정의하기 인터페이스 또는 네임스페이스 definition을 target에 realm realm과 함께 정의하려면 다음 단계를 수행하세요:
  1. attributes를 목록으로 설정합니다. 이 목록은 일반 속성 중 definition의 멤버인 것들입니다.

  2. 제거합니다. attributes에서 속성 중 위조 불가인 것을 모두 제거합니다.

  3. 속성 정의하기: attributes를 definition의 속성으로 target에 realm을 사용해 정의합니다.

정적 속성 정의하기 인터페이스 또는 네임스페이스 definition을 target에, realm realm과 함께 정의하려면 다음 단계를 수행하세요:
  1. attributes를 목록으로 설정합니다. 이 목록은 정적 속성 중 멤버인 것들입니다.

  2. 속성 정의하기: attributes를 definition의 속성으로 target에 realm을 사용해 정의합니다.

위조 불가 일반 속성 정의하기 인터페이스 또는 네임스페이스 definition 을 target에, realm realm과 함께 정의하려면 다음 단계를 수행하세요:
  1. attributes를 목록으로 설정합니다. 이 목록은 위조 불가 일반 속성 중 멤버인 것들입니다.

  2. 속성 정의하기: attributes를 definition의 속성으로 target에 realm을 사용해 정의합니다.

속성 정의하기 attributes를 인터페이스 또는 네임스페이스 definition의 속성으로 target에 realm realm을 사용해 정의하려면 다음 단계를 수행하세요:
  1. 각각의 속성 attr에 대해 attributes에서:

    1. 만약 attr가 realm에서 노출되지 않았다면, continue합니다.

    2. getter를 속성 getter를 생성해서 attr, definition, realm을 인자로 하여 설정합니다.

    3. setter를 속성 setter를 생성해서 attr, definition, realm을 인자로 하여 설정합니다.

      참고: 속성 setter 생성 알고리즘은 attr가 읽기 전용일 경우 undefined를 반환합니다.

    4. configurable를 attr가 위조 불가이면 false로, 그렇지 않으면 true로 설정합니다.

    5. desc를 PropertyDescriptor{[[Getter]]: getter, [[Setter]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}로 설정합니다.

    6. id를 attr의 식별자로 설정합니다.

    7. ! DefinePropertyOrThrow(target, id, desc)를 수행합니다.

    8. 만약 attr의 타입이 observable array type이고 타입 인자가 T라면, target의 backing observable array exotic object를 observable array exotic object 생성하기의 결과로 설정합니다. 인자는 realm, T, attr의 인덱스 값 설정 알고리즘, 인덱스 값 삭제 알고리즘입니다.

속성 getter는 다음과 같이 생성됩니다. 속성 attribute, 네임스페이스 또는 인터페이스 target, realm realm을 인자로 합니다:

  1. steps를 다음 단계들의 연속으로 둔다:

    1. 다음 단계들을 시도한다:

      1. idlObject를 null로 둔다.

      2. target이 인터페이스이고, attribute가 일반 속성이라면:

        1. jsValue를 this 값(단, null 또는 undefined가 아니라면) 아니면 realm의 글로벌 객체로 둔다. (이후 단계에서 글로벌 객체가 target을 구현하지 않고 [LegacyLenientThis] 가 지정되지 않았다면 TypeError가 발생한다.)

        2. jsValue가 플랫폼 객체라면, 보안 검증을 수행한다. jsValue, attribute의 식별자, "getter"를 전달한다.

        3. jsValue가 target을 구현하지 않는다면:

          1. attribute에 [LegacyLenientThis] 확장 속성이 지정되어 있으면 undefined를 반환한다.

          2. 그 외의 경우, 예외를 발생시킨다(throw) TypeError.

        4. attribute의 타입이 observable array 타입라면, jsValue의 backing observable array exotic object를 attribute에 대해 반환한다.

        5. idlObject를 jsValue에 대한 참조를 나타내는 IDL interface 타입의 값으로 설정한다.

      3. R을 attribute의 getter 단계를 idlObject를 this로 하여 실행한 결과로 둔다.

      4. 변환(converting) 결과인 R을 attribute에 선언된 타입의 JavaScript 값으로 반환한다.

    그리고 예외 E가 발생했다면:

    1. attribute의 타입이 promise 타입이면, ! Call(%Promise.reject%, %Promise%, «E»)를 반환한다.

    2. 그 외에는, 이 단계들을 종료하고 예외가 전파되도록 한다.

  2. name을 "get " 문자열을 attribute의 식별자 앞에 붙인 값으로 둔다.

  3. F를 CreateBuiltinFunction(steps, 0, name, « », realm)의 결과로 둔다.

  4. F를 반환한다.

속성 setter 는 다음과 같이 생성됩니다. 속성 attribute, 네임스페이스 또는 인터페이스 target, 그리고 realm realm이 주어졌을 때:

  1. 만약 target이 네임스페이스라면:

    1. 단언: attribute는 읽기 전용이다.

    2. undefined를 반환한다.

  2. 만약 attribute가 읽기 전용이고 [LegacyLenientSetter], [PutForwards] 또는 [Replaceable] 확장 속성이 지정되지 않았다면 undefined를 반환한다. 속성 setter 함수가 존재하지 않는다.

  3. 단언: attribute의 타입은 promise 타입이 아니다.

  4. steps를 다음 단계들의 연속으로 둔다:

    1. V를 undefined로 둔다.

    2. 만약 인자가 전달되었다면, V를 첫 번째 전달된 인자의 값으로 설정한다.

    3. id를 attribute의 식별자로 둔다.

    4. idlObject를 null로 둔다.

    5. attribute가 일반 속성이면:

      1. jsValue를 this 값(단, null 또는 undefined가 아니라면) 아니면 realm의 글로벌 객체로 둔다. (이후 단계에서 글로벌 객체가 target을 구현하지 않고 [LegacyLenientThis] 가 지정되지 않았다면 TypeError가 발생한다.)

      2. jsValue가 플랫폼 객체라면, 보안 검증을 수행한다. jsValue, id, "setter"를 전달한다.

      3. validThis를 jsValue가 target을 구현하면 true, 그렇지 않으면 false로 둔다.

      4. validThis가 false이고 attribute에 [LegacyLenientThis] 확장 속성이 지정되어 있지 않다면, 예외를 발생시킨다(throw) TypeError.

      5. attribute가 [Replaceable] 확장 속성으로 선언되었다면:

        1. ? CreateDataPropertyOrThrow(jsValue, id, V).

        2. undefined를 반환한다.

      6. validThis가 false이면 undefined를 반환한다.

      7. attribute가 [LegacyLenientSetter] 확장 속성으로 선언되었다면, undefined를 반환한다.

      8. attribute가 [PutForwards] 확장 속성으로 선언되었다면:

        1. Q를 ? Get(jsValue, id)로 둔다.

        2. Q가 Object가 아니면, 예외를 발생시킨다(throw) TypeError.

        3. forwardId를 [PutForwards] 확장 속성의 식별자 인자로 둔다.

        4. ? Set(Q, forwardId, V, false)를 수행한다.

        5. undefined를 반환한다.

      9. idlObject를 jsValue에 대한 참조를 나타내는 IDL interface 타입 값으로 설정한다.

      10. attribute의 타입이 타입 인자 T를 가진 observable array 타입이면:

        1. newValues를 변환(converting)한, V를 sequence<T> 타입의 IDL 값으로 변환한 결과로 둔다.

        2. oa를 idlObject의 attribute에 해당하는 backing observable array exotic object로 둔다.

        3. Set the length를 oa.[[ProxyHandler]]에 대해 0으로 수행한다.

        4. i를 0으로 둔다.

        5. i < newValues의 크기인 동안:

          1. oa.[[ProxyHandler]].[[SetAlgorithm]]이 제공하는 알고리즘 단계를 newValues[i]와 i를 인자로 하여 수행한다.

          2. Append newValues[i]를 oa.[[ProxyHandler]].[[BackingList]]에 추가한다.

        6. undefined를 반환한다.

    6. idlValue를 다음과 같이 결정한다:

      attribute의 타입이 열거형인 경우
      1. S를 ? ToString(V)로 둔다.

      2. S가 열거형 값들 중 하나가 아니면 undefined를 반환한다.

      3. 그 외에는, idlValue를 S와 동일한 열거형 값으로 둔다.

      그 외
      idlValue를 변환(converting)한 V를 attribute의 타입의 IDL 값으로 변환한 결과로 둔다.
    7. setter 단계를 attribute에 대해, idlObject를 this, idlValue를 주어진 값으로 하여 수행한다.

    8. undefined를 반환한다.

  5. name을 "set " 문자열을 id 앞에 붙인 값으로 둔다.

  6. F를 CreateBuiltinFunction(steps, 1, name, « », realm)의 결과로 둔다.

  7. F를 반환한다.

참고: IDL 속성에는 단일 프로퍼티만 있지만, 접근자 프로퍼티 getter와 setter는 해당 IDL 속성에 대응하는 프로퍼티가 접근된 객체의 this 값을 전달받으므로 인스턴스별 데이터를 노출할 수 있습니다.

참고: 읽기 전용 속성 에 대응하는 프로퍼티에 값을 할당하려고 하면, 스크립트가 엄격 모드(strict mode)인지에 따라 동작이 달라집니다. 엄격 모드에서는 해당 할당이 TypeError 를 발생시키고, 엄격 모드가 아니면 할당 시도가 무시됩니다.

3.7.7. 연산(Operations)

각 인터페이스에서 정의된, 노출된 연산의 고유한 식별자마다 해당하는 프로퍼티가 존재합니다. 정적 연산은 인터페이스 객체에 노출됩니다. 일반 연산은 인터페이스 프로토타입 객체에 노출됩니다. 단, 연산이 위조 불가이거나, 인터페이스가 [Global] 확장 속성으로 선언된 경우에는, 해당 인터페이스를 구현하는 모든 객체에 노출됩니다.

일반 연산 정의하기 인터페이스 또는 네임스페이스 definition을 target에, realm realm과 함께 정의하려면 다음 단계를 수행하세요:
  1. operations를 목록으로 설정합니다. 이 목록은 일반 연산 중 멤버인 것들입니다.

  2. 제거합니다. operations에서 연산 중 위조 불가인 것들을 모두 제거합니다.

  3. 연산 정의하기: operations를 definition의 연산으로 target에 realm을 사용해 정의합니다.

정적 연산 정의하기 인터페이스 또는 네임스페이스 definition을 target에, realm realm과 함께 정의하려면 다음 단계를 수행하세요:
  1. operations를 목록으로 설정합니다. 이 목록은 정적 연산 중 멤버인 것들입니다.

  2. 연산 정의하기: operations를 definition의 연산으로 target에 realm을 사용해 정의합니다.

위조 불가 일반 연산 정의하기 인터페이스 또는 네임스페이스 definition 을 target에, realm realm과 함께 정의하려면 다음 단계를 수행하세요:
  1. operations를 목록으로 설정합니다. 이 목록은 위조 불가 일반 연산 중 멤버인 것들입니다.

  2. 연산 정의하기: operations를 definition의 연산으로 target에 realm을 사용해 정의합니다.

연산 정의하기 operations를 인터페이스 또는 네임스페이스 definition의 연산으로 target에 realm realm을 사용해 정의하려면 다음 단계를 수행하세요:
  1. 각각의 연산 op에 대해 operations에서:

    1. 만약 op가 realm에서 노출되지 않았다면, continue합니다.

    2. method를 연산 함수 생성하기의 결과로 op, definition, realm을 인자로 하여 설정합니다.

    3. modifiable를 op가 위조 불가이면 false로, 그렇지 않으면 true로 설정합니다.

    4. desc를 PropertyDescriptor{[[Value]]: method, [[Writable]]: modifiable, [[Enumerable]]: true, [[Configurable]]: modifiable}로 설정합니다.

    5. id를 op의 식별자로 설정합니다.

    6. ! DefinePropertyOrThrow(target, id, desc)를 수행합니다.

연산 함수 생성하기 연산 op, 네임스페이스 또는 인터페이스 target, realm realm이 주어졌을 때:
  1. id를 op의 식별자로 둔다.

  2. args를 함수 인자값으로 받았을 때 steps를 다음 단계의 연속으로 둔다:

    1. 다음 단계들을 시도한다:

      1. idlObject를 null로 둔다.

      2. target이 인터페이스이고, op가 정적 연산이 아니라면:

        1. jsValue가 this 값이라면, 이 값이 null 또는 undefined가 아니라면 그대로 두고, 그렇지 않으면 realm의 글로벌 객체로 한다. (이후 몇 단계에서, 글로벌 객체가 target을 구현하지 않으면 TypeError 가 발생한다.)

        2. jsValue가 플랫폼 객체라면, 보안 검사를 수행한다. jsValue, id, "method"를 전달한다.

        3. jsValue가 target 인터페이스를 구현하지 않는다면, 예외를 발생시킨다(throw) TypeError.

        4. idlObject를 jsValue에 대한 참조를 나타내는 IDL interface 타입 값으로 설정한다.

      3. n을 args의 크기로 둔다.

      4. 오버로드 집합을 계산한다. 정규 연산(op이 정규 연산인 경우) 또는 정적 연산(op이 정적 연산인 경우)에 대해, 식별자 id와 target 및 인수 개수 n를 사용하며, 결과를 S로 둔다.

      5. <operation, values>를 S와 args를 오버로드 결정 알고리즘에 전달한 결과로 둔다.

      6. R을 null로 둔다.

      7. operation이 [Default] 확장 속성으로 선언되었다면:

        1. 단언: operation은 default 메서드 단계를 가진다.

        2. R을 operation의 default 메서드 단계를 idlObject를 this, values를 인수값으로 하여 수행한 결과로 설정한다.

      8. 그 외의 경우, operation의 메서드 단계를 idlObject를 this, values를 인수값으로 하여 수행한 결과를 R로 설정한다.

      9. R을 JavaScript 값으로 변환하여 반환한다.

        R은 op이 반환 타입으로 선언한 IDL 값임을 가정한다. [whatwg/webidl Issue #674]

    그리고 예외 E가 발생했다면:

    1. op의 반환 타입 이 promise 타입인 경우, ! Call(%Promise.reject%, %Promise%, «E»)를 반환한다.

    2. 그 외의 경우, 이 단계들을 종료하고 예외가 전파되도록 한다.

  3. 오버로드 집합을 계산한다. 정규 연산(op이 정규 연산인 경우) 또는 정적 연산(op이 정적 연산인 경우)에 대해 식별자 id, target, 인수 개수 0을 사용하고 결과를 S로 둔다.

  4. length를 S의 엔트리들 중 가장 짧은 인수 목록의 길이로 둔다.

  5. F를 CreateBuiltinFunction(steps, length, id, « », realm)의 결과로 둔다.

  6. F를 반환한다.

3.7.7.1. 기본 연산

일반 연산이 기본 메서드 단계를 갖는다 는 그 식별자가 아래 표의 첫 번째 열에 등장하는 경우를 말합니다. 이 경우, 기본 메서드 단계는 표 두 번째 열에서 연결된 알고리즘에 따라 결정되고, 연산은 표 세 번째 열에 명시된 반환 타입을 가져야 합니다.

식별자 기본 메서드 단계 반환 타입
"toJSON" 기본 toJSON 단계 object

일반 연산이 기본 메서드 단계를 갖지 않는다면, [Default] 확장 속성으로 선언하면 안 됩니다.

3.7.7.1.1. 기본 toJSON 연산

기본 toJSON 단계는 인터페이스 I에 대해 다음과 같이 동작합니다:

  1. map을 새로운 순서가 있는 맵으로 설정합니다.

  2. stack을 상속 스택 생성 알고리즘을 인터페이스 I에 대해 실행한 결과로 설정합니다.

  3. 상속 스택의 속성 값 수집 알고리즘을 this, stack, map과 함께 실행합니다.

  4. result를 OrdinaryObjectCreate(%Object.prototype%)의 결과로 설정합니다.

  5. 각 key → value에 대해 map에서:

    1. k를 key 자바스크립트 값으로 변환한 결과로 설정합니다.

    2. v를 value 자바스크립트 값으로 변환한 결과로 설정합니다.

    3. ! CreateDataPropertyOrThrow(result, k, v)를 실행합니다.

  6. result를 반환합니다.

상속 스택의 속성 값 수집 알고리즘은, 플랫폼 객체 object, 스택 stack, 순서가 있는 맵 map이 주어졌을 때 다음과 같이 동작합니다:

  1. I를 stack에서 pop한 결과로 설정합니다.

  2. 속성 값 수집 알고리즘을 object, I, map과 함께 실행합니다.

  3. 만약 stack이 비어있지 않다면, 상속 스택의 속성 값 수집 알고리즘을 object, stack, map과 함께 다시 실행합니다.

속성 값 수집 알고리즘은 플랫폼 객체 object, 인터페이스 I, 순서가 있는 맵 map이 주어졌을 때 다음과 같이 동작합니다:

  1. 만약 I에 [Default] 확장 속성이 붙은 toJSON 연산이 선언되어 있다면, 각 노출된 일반 속성 attr에 대해, 인터페이스 멤버가 I인 것들을 순서대로:

    1. id를 attr의 식별자로 설정합니다.

    2. value를 getter 단계를 attr에 대해 object를 this로 사용해 실행한 결과로 설정합니다.

    3. 만약 value가 JSON 타입이라면, map에 설정하여 map[id]에 value를 지정합니다.

상속 스택 생성 알고리즘은 인터페이스 I에 대해 다음과 같이 동작합니다:

  1. stack을 새로운 스택으로 설정합니다.

  2. stack에 push하여 I를 넣습니다.

  3. while I가 상속하는 인터페이스가 있을 때,

    1. I를 그 인터페이스로 설정합니다.

    2. stack에 push하여 I를 넣습니다.

  4. stack을 반환합니다.

toJSON 연산에 [Default] 확장 속성이 선언된 인터페이스의 일반 속성만 포함되며, 상속된 인터페이스에 해당 연산이 선언되었더라도 포함되지 않습니다. 예를 들어, 아래 IDL fragment를 보세요:

[Exposed=Window]
interface A {
  [Default] object toJSON();
  attribute DOMString a;
};

[Exposed=Window]
interface B : A {
  attribute DOMString b;
};

[Exposed=Window]
interface C : B {
  [Default] object toJSON();
  attribute DOMString c;
};

위에서 정의된 C 인터페이스를 구현한 객체의 toJSON() 메서드를 호출하면 아래와 같은 JSON 객체가 반환됩니다:

{
    "a": "...",
    "c": "..."
}

위에서 정의된 A 또는 B 인터페이스를 구현한 객체의 toJSON() 메서드를 호출하면:

{
    "a": "..."
}

toJSON 연산은 인터페이스 믹스인(또는 부분 인터페이스)에서도 선언할 수 있으며, 이는 원래 인터페이스에 선언하는 것과 동일하게 동작합니다. 예를 들어, 아래 IDL fragment를 보세요:

[Exposed=Window]
interface D {
  attribute DOMString d;
};

interface mixin M {
  [Default] object toJSON();
  attribute DOMString m;
};

D includes M;

위에서 정의된 D 인터페이스를 구현한 객체의 toJSON() 메서드를 호출하면:

{
    "d": "...",
    "m": "..."
}

3.7.8. 문자열화자(Stringifiers)

인터페이스에 노출된 문자열화자(stringifier)가 있다면, 다음 특성을 가진 프로퍼티가 반드시 존재해야 합니다:

3.7.9. 이터러블 선언

이터레이션 메서드 정의하기 인터페이스 definition을 target에, realm realm과 함께 정의하려면 다음 단계를 수행하세요:
  1. 만약 definition에 인덱스 프로퍼티 getter가 있다면:

    1. DefineMethodProperty(target, %Symbol.iterator%, %Array.prototype.values%, false)를 수행합니다.

    2. 만약 definition에 값 이터레이터가 있다면:

      1. ! CreateDataPropertyOrThrow(target, "entries", %Array.prototype.entries%)를 수행합니다.

      2. ! CreateDataPropertyOrThrow(target, "keys", %Array.prototype.keys%)를 수행합니다.

      3. ! CreateDataPropertyOrThrow(target, "values", %Array.prototype.values%)를 수행합니다.

      4. ! CreateDataPropertyOrThrow(target, "forEach", %Array.prototype.forEach%)를 수행합니다.

  2. 그렇지 않고 definition에 쌍 이터레이터가 있다면:

    1. %Symbol.iterator% 및 entries 메서드를 정의한다:

      1. steps를 다음 일련의 단계로 둔다:

        1. jsValue를 ? ToObject(this 값)으로 둔다.

        2. jsValue가 플랫폼 객체라면, 보안 검증을 수행한다. jsValue, "%Symbol.iterator%", "method"를 전달한다.

        3. jsValue가 definition을 구현하지 않는다면, 예외를 발생시킨다(throw) TypeError.

        4. definition에 대해 새로 생성된 기본 반복자 객체(default iterator object)를 반환한다. jsValue를 target으로, "key+value"를 kind로, index는 0으로 한다.

      2. F를 CreateBuiltinFunction(steps, 0, "entries", « », realm)로 둔다.

      3. DefineMethodProperty(target, %Symbol.iterator%, F, false)를 수행한다.

      4. ! CreateDataPropertyOrThrow(target, "entries", F)를 수행한다.

    2. keys 메서드를 정의한다:

      1. steps를 다음 일련의 단계로 둔다:

        1. jsValue를 ? ToObject(this 값)으로 둔다.

        2. jsValue가 플랫폼 객체라면, 보안 검증을 수행한다. jsValue, "keys", "method"를 전달한다.

        3. jsValue가 definition을 구현하지 않는다면, 예외를 발생시킨다(throw) TypeError.

        4. definition에 대해 새로 생성된 기본 반복자 객체(default iterator object)를 반환한다. jsValue를 target으로, "key"를 kind로, index는 0으로 한다.

      2. F를 CreateBuiltinFunction(steps, 0, "keys", « », realm)로 둔다.

      3. ! CreateDataPropertyOrThrow(target, "keys", F)를 수행한다.

    3. values 메서드를 정의한다:

      1. steps를 다음 일련의 단계로 둔다:

        1. jsValue를 ? ToObject(this 값)으로 둔다.

        2. jsValue가 플랫폼 객체라면, 보안 검증을 수행한다. jsValue, "values", "method"를 전달한다.

        3. jsValue가 definition을 구현하지 않는다면, 예외를 발생시킨다(throw) TypeError.

        4. definition에 대해 새로 생성된 기본 반복자 객체(default iterator object)를 반환한다. jsValue를 target으로, "value"를 kind로, index는 0으로 한다.

      2. F를 CreateBuiltinFunction(steps, 0, "values", « », realm)로 둔다.

      3. ! CreateDataPropertyOrThrow(target, "values", F)를 수행한다.

    4. forEach 메서드를 정의한다:

      1. 함수 인자값 callback 및 thisArg를 받았을 때 steps를 다음 일련의 단계로 둔다:

        1. jsValue를 ? ToObject(this 값)으로 둔다.

        2. jsValue가 플랫폼 객체라면, 보안 검증을 수행한다. jsValue, "forEach", "method"를 전달한다.

        3. jsValue가 definition을 구현하지 않는다면, 예외를 발생시킨다(throw) TypeError.

        4. idlCallback를 callback을 IDL 값으로 변환(Function 타입)한 값으로 둔다.

        5. idlObject를 jsValue에 대한 참조를 나타내는 IDL interface 타입 값으로 설정한다.

        6. pairs를 idlObject의 반복해야 하는 값 쌍(value pairs to iterate over)의 리스트로 둔다.

        7. i를 0으로 둔다.

        8. i < pairs의 크기일 동안:

          1. pair를 pairs[i]로 둔다.

          2. 콜백 함수 호출을 수행한다. idlCallback에 « pair의 value, pair의 key, idlObject » 및 thisArg를 콜백 this 값으로 하여 호출한다.

          3. pairs를 idlObject의 현재 반복해야 하는 값 쌍 리스트로 다시 설정한다. (중간에 변경될 수도 있다.)

          4. i를 i + 1로 설정한다.

      2. F를 CreateBuiltinFunction(steps, 1, "forEach", « », realm)로 둔다.

      3. ! CreateDataPropertyOrThrow(target, "forEach", F)를 수행한다.

3.7.9.1. 기본 이터레이터 객체

기본 이터레이터 객체는 지정된 인터페이스, target, 이터레이션 kind에 대해 [[Prototype]] 내부 슬롯이 해당 인터페이스의 이터레이터 프로토타입 객체인 객체입니다.

기본 이터레이터 객체는 세 가지 내부 값을 가집니다:

참고: 기본 이터레이터 객체는 쌍 이터레이터에만 사용됩니다. 값 이터레이터는 현재 객체의 지원하는 인덱스 프로퍼티만 이터레이션하도록 제한되어 있으므로, 표준 JavaScript Array 이터레이터 객체를 사용합니다.

참고: 기본 이터레이터 객체는 클래스 문자열을 가지지 않습니다; Object.prototype.toString()을 인터페이스의 기본 이터레이터 객체에 호출하면, 해당 인터페이스의 이터레이터 프로토타입 객체의 클래스 문자열이 사용됩니다.

3.7.9.2. 이터레이터 프로토타입 객체

이터레이터 프로토타입 객체는 지정된 인터페이스에 대해 쌍 이터레이터가 있는 모든 인터페이스에 존재합니다. 해당 인터페이스의 기본 이터레이터 객체의 프로토타입 역할을 합니다.

[[Prototype]] 내부 슬롯은 이터레이터 프로토타입 객체에서 %Iterator.prototype%이어야 합니다.

이터레이터 결과는 값 쌍 pair와 kind kind에 대해 다음 단계로 결정합니다:
  1. kind 값에 따라 result를 다음과 같이 결정합니다:

    "key"
    1. idlKey를 pair의 key로 설정합니다.

    2. key를 IDL to JS 값 변환하여 idlKey를 자바스크립트 값으로 변환한 결과로 설정합니다.

    3. result는 key입니다.

    "value"
    1. idlValue를 pair의 value로 설정합니다.

    2. value를 IDL to JS 값 변환하여 idlValue를 자바스크립트 값으로 변환한 결과로 설정합니다.

    3. result는 value입니다.

    "key+value"
    1. idlKey를 pair의 key로 설정합니다.

    2. idlValue를 pair의 value로 설정합니다.

    3. key를 IDL to JS 값 변환하여 idlKey를 자바스크립트 값으로 변환한 결과로 설정합니다.

    4. value를 IDL to JS 값 변환하여 idlValue를 자바스크립트 값으로 변환한 결과로 설정합니다.

    5. array를 ! ArrayCreate(2)로 설정합니다.

    6. ! CreateDataPropertyOrThrow(array, "0", key)를 수행합니다.

    7. ! CreateDataPropertyOrThrow(array, "1", value)를 수행합니다.

    8. result는 array입니다.

  2. CreateIteratorResultObject(result, false)를 반환합니다.

이터레이터 프로토타입 객체는 속성이 { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }인 next 데이터 프로퍼티를 가져야 하며, 그 값은 내장 함수 객체 CreateBuiltinFunction(nextSteps, 0, "next", « »)이어야 한다. 여기서 nextSteps는 다음 알고리즘이다:

  1. interface를 해당 이터레이터 프로토타입 객체가 존재하는 인터페이스로 설정합니다.

  2. thisValue를 this 값으로 설정합니다.

  3. object를 ? ToObject(thisValue)로 설정합니다.

  4. object가 플랫폼 객체이면, 보안 검사 수행을 다음 인자로 하여 실행합니다:

    • 플랫폼 객체 object,

    • 식별자 "next",

    • 타입 "method"

  5. object가 interface의 기본 이터레이터 객체가 아니면, throw를 사용해 TypeError를 발생시킵니다.

  6. index를 object의 index로 설정합니다.

  7. kind를 object의 kind로 설정합니다.

  8. values를 object의 target의 이터레이션 할 값 쌍 목록으로 설정합니다.

  9. len을 values의 길이로 설정합니다.

  10. index가 len보다 크거나 같으면, CreateIteratorResultObject(undefined, true)를 반환합니다.

  11. pair를 values의 index번째 엔트리로 설정합니다.

  12. object의 index를 index + 1로 설정합니다.

  13. 이터레이터 결과를 pair, kind에 대해 반환합니다.

지정된 인터페이스에 대한 이터레이터 프로토타입 객체의 클래스 문자열은 해당 인터페이스의 식별자와 문자열 " Iterator"를 연결한 결과입니다.

3.7.10. 비동기 이터러블 선언

비동기 이터레이션 메서드 정의하기 인터페이스 definition 을 target에, realm realm과 함께 정의하려면 다음 단계를 수행하세요:
  1. definition에 비동기 반복 가능 선언(두 종류 모두 포함)이 없다면, 반환한다.

  2. 단언: definition에 인덱스드 프로퍼티 게터 또는 iterable 선언이 없어야 한다.

  3. definition에 pair 비동기 반복 가능 선언이 있다면, %Symbol.asyncIterator% 와 entries 메서드를 정의한다:

    1. 함수 인자값 args가 주어진 경우, steps를 다음과 같이 둔다:

      1. jsValue를 ? ToObject(this 값)으로 둔다.

      2. jsValue가 플랫폼 객체라면, 보안 검증을 수행한다. jsValue, "%Symbol.asyncIterator%", "method"를 전달한다.

      3. jsValue가 definition을 구현하지 않는다면, 예외를 발생시킨다(throw) TypeError.

      4. idlObject를 jsValue에 대한 참조를 나타내는 IDL interface 타입 값으로 둔다.

      5. idlArgs를 비동기 반복자 메서드의 인자 변환 결과(args 사용)로 둔다.

      6. iterator를 definition에 대해 새롭게 생성한 기본 비동기 반복자 객체로 둔다. idlObject를 target으로, "key+value"를 kind로, is finished는 false로 둔다.

      7. definition에 대해 idlObject, iterator, idlArgs를 인자로 하여, 비동기 반복자 초기화 단계가 정의되어 있으면 실행한다.

      8. iterator를 반환한다.

    2. F를 CreateBuiltinFunction(steps, 0, "entries", « », realm)로 둔다.

    3. DefineMethodProperty(target, %Symbol.asyncIterator%, F, false)를 수행한다.

    4. ! CreateDataPropertyOrThrow(target, "entries", F)를 수행한다.

  4. definition에 pair 비동기 반복 가능 선언이 있다면, keys 메서드를 정의한다:

    1. 함수 인자값 args가 주어진 경우, steps를 다음과 같이 둔다:

      1. jsValue를 ? ToObject(this 값)으로 둔다.

      2. jsValue가 플랫폼 객체라면, 보안 검증을 수행한다. jsValue, "keys", "method"를 전달한다.

      3. jsValue가 definition을 구현하지 않는다면, 예외를 발생시킨다(throw) TypeError.

      4. idlObject를 jsValue에 대한 참조를 나타내는 IDL interface 타입 값으로 둔다.

      5. idlArgs를 비동기 반복자 메서드의 인자 변환 결과(args 사용)로 둔다.

      6. iterator를 definition에 대해 새롭게 생성한 기본 비동기 반복자 객체로 둔다. idlObject를 target으로, "key"를 kind로, is finished는 false로 둔다.

      7. definition에 대해 idlObject, iterator, idlArgs를 인자로 하여, 비동기 반복자 초기화 단계가 정의되어 있으면 실행한다.

      8. iterator를 반환한다.

    2. F를 CreateBuiltinFunction(steps, 0, "keys, « », realm)로 둔다.

    3. ! CreateDataPropertyOrThrow(target, "keys", F)를 수행한다.

  5. values (그리고 필요시 %Symbol.asyncIterator%) 메서드를 정의한다:

    1. 함수 인자값 args가 주어진 경우, steps를 다음과 같이 둔다:

      1. jsValue를 ? ToObject(this 값)으로 둔다.

      2. jsValue가 플랫폼 객체라면, 보안 검증을 수행한다. jsValue, "values", "method"를 전달한다.

      3. jsValue가 definition을 구현하지 않는다면, 예외를 발생시킨다(throw) TypeError.

      4. idlObject를 jsValue에 대한 참조를 나타내는 IDL interface 타입 값으로 둔다.

      5. idlArgs를 비동기 반복자 메서드의 인자 변환 결과(args 사용)로 둔다.

      6. iterator를 definition에 대해 새롭게 생성한 기본 비동기 반복자 객체로 둔다. idlObject를 target으로, "value"를 kind로, is finished는 false로 둔다.

      7. definition에 대해 idlObject, iterator, idlArgs를 인자로 하여, 비동기 반복자 초기화 단계가 정의되어 있으면 실행한다.

      8. iterator를 반환한다.

    2. F를 CreateBuiltinFunction(steps, 0, "values", « », realm)로 둔다.

    3. ! CreateDataPropertyOrThrow(target, "values", F)를 수행한다.

    4. definition에 value 비동기 반복 가능 선언이 있으면, ! DefineMethodProperty(target, %Symbol.asyncIterator%, F, false)를 수행한다.

비동기 이터레이터 메서드 인자 변환 알고리즘은, 인터페이스 definition이 비동기 이터러블 선언을 가지고 있고 자바스크립트 값의 목록 args가 주어졌을 때 다음과 같이 동작합니다:
  1. idlArgs를 빈 리스트로 설정합니다.

  2. argCount를 definition의 비동기 이터러블 선언의 인자 개수로 설정하거나, 비동기 이터러블 선언에 인자 리스트가 없으면 0으로 설정합니다.

  3. i를 0으로 설정합니다.

  4. i < argCount일 동안:

    1. 만약 i ≥ args의 크기이거나, args[i]가 undefined이면, 다음을 수행합니다:

      1. 만약 i번째 비동기 이터러블 선언의 인자가 기본값으로 선언되어 있다면, 그 기본값을 idlArgs에 추가합니다.

      2. 그렇지 않으면, idlArgs에 "missing" 특수 값을 추가합니다.

    2. 그 외의 경우, idlArgs에 추가합니다. ECMAScript 값을 해당 타입의 IDL 값으로 변환하여 args[i]를 비동기 이터러블 선언의 인자 리스트 i번째 타입으로 변환한 결과를 추가합니다.

    3. i를 i + 1로 설정합니다.

  5. idlArgs를 반환합니다.

이 알고리즘은 오버로드 해결 알고리즘을 오버로드가 허용되지 않고 모든 인자가 옵션인 경우로 특화한 것입니다.

3.7.10.1. 기본 비동기 이터레이터 객체

기본 비동기 이터레이터 객체는 지정된 인터페이스, target, 이터레이션 kind에 대해 [[Prototype]] 내부 슬롯이 해당 인터페이스의 비동기 이터레이터 프로토타입 객체인 객체입니다.

기본 비동기 이터레이터 객체는 내부 값을 가집니다:

참고: 기본 비동기 이터레이터 객체는 클래스 문자열을 가지지 않습니다. Object.prototype.toString()을 지정된 인터페이스의 기본 비동기 이터레이터 객체에 호출하면, 해당 인터페이스의 비동기 이터레이터 프로토타입 객체의 클래스 문자열이 사용됩니다.

3.7.10.2. 비동기 이터레이터 프로토타입 객체

비동기 이터레이터 프로토타입 객체 는 지정된 인터페이스에 대해, 비동기 이터러블 선언을 가진 모든 인터페이스에 존재하는 객체입니다. 해당 인터페이스의 기본 비동기 이터레이터 객체의 프로토타입 역할을 합니다.

비동기 이터레이터 프로토타입 객체의 [[Prototype]] 내부 슬롯은 %AsyncIteratorPrototype%이어야 합니다.

비동기 이터레이터 프로토타입 객체는 속성이 { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }인 next 데이터 프로퍼티를 가져야 하며, 그 값은 내장 함수 객체 CreateBuiltinFunction(nextSteps, 0, "next", « »)이어야 한다. 여기서 nextSteps는 다음 알고리즘이다:

  1. interface를 해당 비동기 이터레이터 프로토타입 객체가 존재하는 인터페이스로 설정합니다.

  2. thisValidationPromiseCapability를 ! NewPromiseCapability(%Promise%)로 설정합니다.

  3. thisValue를 this 값으로 설정합니다.

  4. object를 Completion(ToObject(thisValue))로 설정합니다.

  5. IfAbruptRejectPromise(object, thisValidationPromiseCapability)를 실행합니다.

  6. object가 플랫폼 객체이면 보안 검사 수행을 다음 인자로 하여 실행합니다:

    • 플랫폼 객체 object,

    • 식별자 "next",

    • 타입 "method"

    여기서 예외 e가 발생했다면:

    1. ! Call(thisValidationPromiseCapability.[[Reject]], undefined, « e »)를 실행합니다.

    2. thisValidationPromiseCapability.[[Promise]]를 반환합니다.

  7. object가 interface의 기본 비동기 이터레이터 객체가 아니면:

    1. error를 새 TypeError로 설정합니다.

    2. ! Call(thisValidationPromiseCapability.[[Reject]], undefined, « error »)를 실행합니다.

    3. thisValidationPromiseCapability.[[Promise]]를 반환합니다.

  8. nextSteps를 다음 단계로 설정합니다:

    1. nextPromiseCapability를 ! NewPromiseCapability(%Promise%)로 설정합니다.

    2. object의 is finished가 true라면:

      1. result를 CreateIteratorResultObject(undefined, true)로 설정합니다.

      2. ! Call(nextPromiseCapability.[[Resolve]], undefined, « result »)를 실행합니다.

      3. nextPromiseCapability.[[Promise]]를 반환합니다.

    3. kind를 object의 kind로 설정합니다.

    4. nextPromise를 다음 이터레이션 결과 가져오기 알고리즘을 object의 target과 object에 대해 실행한 결과로 설정합니다.

    5. fulfillSteps를 다음 단계로 설정합니다. next가 주어졌을 때:

      1. object의 ongoing promise 를 null로 설정합니다.

      2. next가 이터레이션 종료라면:

        1. object의 is finished를 true로 설정합니다.

        2. CreateIteratorResultObject(undefined, true)를 반환합니다.

      3. 그 외의 경우, interface에 쌍 비동기 이터러블 선언이 있다면:

        1. 단언: next는 값 쌍이다.

        2. 이터레이터 결과를 next, kind에 대해 반환합니다.

      4. 그 외의 경우:

        1. 단언: interface에 값 비동기 이터러블 선언이 있다.

        2. 단언: next는 선언에 나오는 타입의 값이다.

        3. value를 next 자바스크립트 값으로 변환한 결과로 설정합니다.

        4. CreateIteratorResultObject(value, false)를 반환합니다.

    6. onFulfilled를 CreateBuiltinFunction(fulfillSteps, 1, "", « »)로 설정합니다.

    7. rejectSteps를 다음 단계로 설정합니다. reason이 주어진 경우:

      1. object의 ongoing promise 를 null로 설정합니다.

      2. object의 is finished를 true로 설정합니다.

      3. Throw reason을 실행합니다.

    8. onRejected를 CreateBuiltinFunction(rejectSteps, 1, "", « »)로 설정합니다.

    9. PerformPromiseThen(nextPromise, onFulfilled, onRejected, nextPromiseCapability)를 실행합니다.

    10. nextPromiseCapability.[[Promise]]를 반환합니다.

  9. ongoingPromise를 object의 ongoing promise로 설정합니다.

  10. ongoingPromise가 null이 아니면:

    1. afterOngoingPromiseCapability를 ! NewPromiseCapability(%Promise%)로 설정합니다.

    2. onSettled를 CreateBuiltinFunction(nextSteps, 0, "", « »)로 설정합니다.

    3. PerformPromiseThen(ongoingPromise, onSettled, onSettled, afterOngoingPromiseCapability)를 실행합니다.

    4. object의 ongoing promise를 afterOngoingPromiseCapability.[[Promise]]로 설정합니다.

  11. 그 외의 경우:

    1. object의 ongoing promise를 nextSteps 실행 결과로 설정합니다.

  12. object의 ongoing promise를 반환합니다.

비동기 이터레이터 return 알고리즘이 해당 인터페이스에 대해 정의되어 있다면, 비동기 이터레이터 프로토타입 객체는 속성이 { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }인 return 데이터 프로퍼티를 가져야 하며, 그 값은 내장 함수 객체 CreateBuiltinFunction(returnSteps, 1, "return", « »)이어야 한다. 여기서 returnSteps는 하나의 인수 value를 받는 다음 알고리즘이다:

  1. interface를 해당 비동기 이터레이터 프로토타입 객체가 존재하는 인터페이스로 설정합니다.

  2. returnPromiseCapability를 ! NewPromiseCapability(%Promise%)로 설정합니다.

  3. thisValue를 this 값으로 설정합니다.

  4. object를 Completion(ToObject(thisValue))로 설정합니다.

  5. IfAbruptRejectPromise(object, returnPromiseCapability)를 실행합니다.

  6. object가 플랫폼 객체이면 보안 검사 수행을 다음 인자로 하여 실행합니다:

    • 플랫폼 객체 object,

    • 식별자 "return",

    • 타입 "method"

    여기서 예외 e가 발생했다면:

    1. ! Call(returnPromiseCapability.[[Reject]], undefined, « e »)를 실행합니다.

    2. returnPromiseCapability.[[Promise]]를 반환합니다.

  7. object가 interface의 기본 비동기 이터레이터 객체가 아니면:

    1. error를 새 TypeError로 설정합니다.

    2. ! Call(returnPromiseCapability.[[Reject]], undefined, « error »)를 실행합니다.

    3. returnPromiseCapability.[[Promise]]를 반환합니다.

  8. returnSteps를 다음 단계로 설정합니다:

    1. returnPromiseCapability를 ! NewPromiseCapability(%Promise%)로 다시 설정합니다.

    2. object의 is finished가 true라면:

      1. result를 CreateIteratorResultObject(value, true)로 설정합니다.

      2. ! Call(returnPromiseCapability.[[Resolve]], undefined, « result »)를 실행합니다.

      3. returnPromiseCapability.[[Promise]]를 반환합니다.

    3. object의 is finished를 true로 설정합니다.

    4. 비동기 이터레이터 리턴 알고리즘을 interface, object의 target, object, value로 실행한 결과를 반환합니다.

  9. ongoingPromise를 object의 ongoing promise로 설정합니다.

  10. ongoingPromise가 null이 아니면:

    1. afterOngoingPromiseCapability를 ! NewPromiseCapability(%Promise%)로 설정합니다.

    2. onSettled를 CreateBuiltinFunction(returnSteps, 0, "", « »)로 설정합니다.

    3. PerformPromiseThen(ongoingPromise, onSettled, onSettled, afterOngoingPromiseCapability)를 실행합니다.

    4. object의 ongoing promise를 afterOngoingPromiseCapability.[[Promise]]로 설정합니다.

  11. 그 외의 경우:

    1. object의 ongoing promise를 returnSteps 실행 결과로 설정합니다.

  12. fulfillSteps를 다음 단계로 설정합니다:

    1. CreateIteratorResultObject(value, true)를 반환합니다.

  13. onFulfilled를 CreateBuiltinFunction(fulfillSteps, 1, "", « »)로 설정합니다.

  14. PerformPromiseThen(object의 ongoing promise, onFulfilled, undefined, returnPromiseCapability)를 실행합니다.

  15. returnPromiseCapability.[[Promise]]를 반환합니다.

지정된 인터페이스에 대한 비동기 이터레이터 프로토타입 객체의 클래스 문자열은 해당 인터페이스의 식별자와 문자열 " AsyncIterator"를 연결한 결과입니다.

3.7.11. 맵라이크 선언

만약 인터페이스 A가 맵라이크 선언으로 선언되었다면, A의 인터페이스 프로토타입 객체에 추가 프로퍼티가 존재합니다. 이 추가 프로퍼티들은 아래 하위 섹션에서 설명합니다.

3.7.11.1. size

A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 size 프로퍼티가 반드시 존재해야 합니다:

3.7.11.2. %Symbol.iterator%

A의 인터페이스 프로토타입 객체에는 이름이 %Symbol.iterator% 심벌인 데이터 프로퍼티가 존재해야 하며, 이 프로퍼티는 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } 속성을 가지고 그 값은 entries 프로퍼티의 값인 함수 객체이다.

맵 이터레이터 생성하기 맵 map과 kind (값: "key+value", "key", "value")가 주어졌을 때:
  1. closure를 추상 클로저(Abstract Closure)로 생성합니다. 파라미터 없이 map과 kind를 캡처하며, 호출 시 다음 단계를 수행합니다:

    1. 각 key → value에 대해 map에서:

      1. key와 value를 각각 자바스크립트 값으로 변환합니다.

      2. kind가 "key"이면 result를 key로 설정합니다.

      3. 그 외 kind가 "value"이면 result를 value로 설정합니다.

      4. 그 외의 경우 result를 CreateArrayFromList(« key, value »)로 설정합니다.

      5. ? GeneratorYield(CreateIteratorResultObject(result, false))를 실행합니다.

      참고: map의 크기와 엔트리 순서는 Yield로 인해 이 추상 연산이 일시 중지되는 동안 변경될 수 있습니다.

    2. undefined를 반환합니다.

  2. CreateIteratorFromClosure(closure, "%MapIteratorPrototype%", %MapIteratorPrototype%)를 반환합니다.

3.7.11.3. entries

A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 entries 데이터 프로퍼티가 반드시 존재해야 합니다:

3.7.11.4. keys

A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 keys 데이터 프로퍼티가 반드시 존재해야 합니다:

3.7.11.5. values

A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 values 데이터 프로퍼티가 반드시 존재해야 합니다:

3.7.11.6. forEach

A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 forEach 데이터 프로퍼티가 반드시 존재해야 합니다:

3.7.11.7. get

A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 get 데이터 프로퍼티가 반드시 존재해야 합니다:

3.7.11.8. has

A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 has 데이터 프로퍼티가 반드시 존재해야 합니다:

3.7.11.9. set

만약 A가 식별자 "set"을 가진 멤버를 선언하지 않았고, A가 읽기-쓰기 맵라이크 선언으로 선언되었다면, A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 set 데이터 프로퍼티가 반드시 존재해야 합니다:

인터페이스가 set 메서드를 선언하는 경우, 마찬가지로 -0 키를 +0으로 매핑해야 하며, this를 반환해야 한다.

3.7.11.10. delete

만약 A가 식별자 "delete"를 가진 멤버를 선언하지 않았고, A가 읽기-쓰기 맵라이크 선언으로 선언되었다면, A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 delete 데이터 프로퍼티가 반드시 존재해야 합니다:

인터페이스가 delete 메서드를 선언하는 경우, 마찬가지로 -0 키를 +0으로 매핑해야 하며, 키가 존재했는지 여부를 나타내는 boolean을 반환해야 한다.

3.7.11.11. clear

만약 A가 식별자 "clear"를 가진 멤버를 선언하지 않았고, A가 읽기-쓰기 맵라이크 선언으로 선언되었다면, A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 clear 데이터 프로퍼티가 반드시 존재해야 합니다:

인터페이스가 clear 메서드를 선언하는 경우, 맵 엔트리 객체를 (새 객체를 생성하는 대신) 보존해야 하며, undefined를 반환해야 한다.

3.7.12. 셋라이크 선언

만약 인터페이스 A가 셋라이크 선언으로 선언되었다면, A의 인터페이스 프로토타입 객체에 추가 프로퍼티가 존재합니다. 이 추가 프로퍼티들은 아래 하위 섹션에서 설명합니다.

3.7.12.1. size

A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 size 프로퍼티가 반드시 존재해야 합니다:

3.7.12.2. %Symbol.iterator%

A의 인터페이스 프로토타입 객체에는 이름이 %Symbol.iterator% 심벌인 데이터 프로퍼티가 존재해야 하며, 이 프로퍼티는 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } 속성을 가지고 그 값은 values 프로퍼티의 값인 함수 객체이다.

셋 이터레이터 생성하기 셋 set과 kind (값: "key+value" 또는 "value")가 주어졌을 때:
  1. closure를 추상 클로저(Abstract Closure)로 생성합니다. 파라미터 없이 set과 kind를 캡처하며, 호출 시 다음 단계를 수행합니다:

    1. 각 entry에 대해 set에서:

      1. entry를 자바스크립트 값으로 변환합니다.

      2. kind가 "value"이면 result를 entry로 설정합니다.

      3. 그 외의 경우 result를 CreateArrayFromList(« entry, entry »)로 설정합니다.

      4. ? GeneratorYield(CreateIteratorResultObject(result, false))를 실행합니다.

      참고: set의 크기와 엔트리 순서는 Yield로 인해 이 추상 연산이 일시 중지된 동안 변경될 수 있습니다.

    2. undefined를 반환합니다.

  2. CreateIteratorFromClosure(closure, "%SetIteratorPrototype%", %SetIteratorPrototype%)를 반환합니다.

3.7.12.3. entries

A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 entries 데이터 프로퍼티가 반드시 존재해야 합니다:

3.7.12.4. keys

keys 데이터 프로퍼티는 A의 인터페이스 프로토타입 객체에 존재해야 하며, { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true } 속성을 가지고 그 값은 values 프로퍼티의 값인 함수 객체이다.

3.7.12.5. values

A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 values 데이터 프로퍼티가 반드시 존재해야 합니다:

3.7.12.6. forEach

A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 forEach 데이터 프로퍼티가 반드시 존재해야 합니다:

3.7.12.7. has

A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 has 데이터 프로퍼티가 반드시 존재해야 합니다:

3.7.12.8. add

만약 A가 식별자 "add"를 가진 멤버를 선언하지 않았고, A가 읽기-쓰기 셋라이크 선언으로 선언되었다면, A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 add 데이터 프로퍼티가 반드시 존재해야 합니다:

인터페이스가 add 메서드를 선언하는 경우, 마찬가지로 -0 값을 +0으로 매핑해야 하며, 설정된 값을 반환해야 한다.

3.7.12.9. delete

만약 A가 식별자 "delete"를 가진 멤버를 선언하지 않았고, A가 읽기-쓰기 셋라이크 선언으로 선언되었다면, A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 delete 데이터 프로퍼티가 반드시 존재해야 합니다:

인터페이스가 delete 메서드를 선언하는 경우, 마찬가지로 -0 값을 +0으로 매핑해야 하며, 값이 존재했는지 여부를 나타내는 boolean을 반환해야 한다.

3.7.12.10. clear

만약 A가 식별자 "clear"를 가진 멤버를 선언하지 않았고, A가 읽기-쓰기 셋라이크 선언으로 선언되었다면, A의 인터페이스 프로토타입 객체에는 다음 특성을 가지는 clear 데이터 프로퍼티가 반드시 존재해야 합니다:

인터페이스가 clear 메서드를 선언하는 경우, 세트 엔트리 객체를 (새 객체를 생성하는 대신) 보존해야 하며, undefined를 반환해야 한다.

3.8. 인터페이스를 구현하는 플랫폼 객체

자바스크립트 값 value가 플랫폼 객체임은 value가 객체(Object)이고, value가 [[PrimaryInterface]] 내부 슬롯을 가지고 있을 때입니다.
자바스크립트 값 value가 인터페이스 interface를 구현한다는 것은 value가 플랫폼 객체이고, value.[[PrimaryInterface]]의 포함된 상속 인터페이스 목록에 interface가 포함되어 있을 때입니다.

명세서는 "object가 interface 객체이다" 등 다양한 방식으로 "object가 interface를 구현한다"는 개념을 참조할 수 있습니다.

모든 플랫폼 객체는 realm과 연관되어 있습니다. 초기 객체들도 마찬가지입니다. 이 realm은 플랫폼 객체의 [[Realm]] 슬롯에 저장됩니다. Web IDL을 사용하는 명세서는 각 플랫폼 객체가 어떤 realm(혹은 그에 대응하는 글로벌 객체)에 속하는지 명시해야 합니다. 특히, 아래 알고리즘은 새 플랫폼 객체를 전달받은 realm에 연관시킵니다.

인터페이스를 구현하는 새 객체 생성하기: realm realm에서 interface를 구현하는 객체를 생성하려면 다음 단계를 수행합니다:
  1. 인터페이스를 내부적으로 구현하는 새 객체 생성 알고리즘을 interface, realm, undefined로 실행한 결과를 반환합니다.

인터페이스를 내부적으로 구현하는 새 객체 생성하기: realm realm과 자바스크립트 값 newTarget을 전달받아 interface를 구현하는 객체를 생성하려면 다음 단계를 수행합니다:
  1. 단언: interface는 realm에 노출되어 있다.

  2. newTarget이 undefined이면:

    1. prototype을 realm의 interface에 대한 인터페이스 프로토타입 객체로 설정합니다.

  3. 그 외의 경우:

    1. 단언: IsCallable(newTarget)가 true이다.

    2. prototype을 ? Get(newTarget, "prototype")의 결과로 설정합니다.

    3. prototype이 객체가 아니면:

      1. targetRealm을 ? GetFunctionRealm(newTarget)의 결과로 설정합니다.

      2. prototype을 targetRealm의 interface에 대한 인터페이스 프로토타입 객체로 설정합니다.

  4. slots를 « [[Prototype]], [[Extensible]], [[Realm]], [[PrimaryInterface]] »로 설정합니다.

  5. interface가 DOMException이면, [[ErrorData]]를 slots에 추가합니다.

  6. instance를 MakeBasicObject(slots)로 생성합니다.

  7. instance.[[Realm]]에 realm을 할당합니다.

  8. instance.[[PrimaryInterface]]에 interface를 할당합니다.

  9. instance.[[Prototype]]에 prototype을 할당합니다.

  10. interfaces를 interface의 포함된 상속 인터페이스 목록으로 설정합니다.

  11. 각 인터페이스 ancestor interface에 대해 interfaces에서:

    1. unforgeables를 realm의 ancestor interface 인터페이스 객체의 [[Unforgeables]] 슬롯 값으로 설정합니다.

    2. keys를 ! unforgeables.[[OwnPropertyKeys]]()의 결과로 설정합니다.

    3. 각 key에 대해 keys에서:

      1. descriptor를 ! unforgeables.[[GetOwnProperty]](key)로 설정합니다.

      2. ! DefinePropertyOrThrow(instance, key, descriptor)를 실행합니다.

  12. interface가 [Global] 확장 속성으로 선언되었다면:

    1. 정규 연산 정의하기 알고리즘을 interface, instance, realm에 대해 실행합니다.

    2. 정규 속성 정의하기 알고리즘을 interface, instance, realm에 대해 실행합니다.

    3. 이터레이션 메서드 정의하기 알고리즘을 interface, instance, realm에 대해 실행합니다.

    4. 비동기 이터레이션 메서드 정의하기 알고리즘을 interface, instance, realm에 대해 실행합니다.

    5. 글로벌 프로퍼티 참조 정의하기 알고리즘을 instance, realm에 대해 실행합니다.

    6. instance.[[SetPrototypeOf]]를 § 3.8.1 [[SetPrototypeOf]]에서 정의된 대로 설정합니다.

  13. 그 외의 경우, interfaces에 인터페이스가 있고, 인덱스 프로퍼티 지원 또는 이름 프로퍼티 지원 인터페이스가 포함되어 있다면:

    1. instance.[[GetOwnProperty]]를 § 3.9.1 [[GetOwnProperty]]에서 정의된 대로 설정합니다.

    2. instance.[[Set]]을 § 3.9.2 [[Set]]에서 정의된 대로 설정합니다.

    3. instance.[[DefineOwnProperty]]를 § 3.9.3 [[DefineOwnProperty]]에서 정의된 대로 설정합니다.

    4. instance.[[Delete]]를 § 3.9.4 [[Delete]]에서 정의된 대로 설정합니다.

    5. instance.[[PreventExtensions]]를 § 3.9.5 [[PreventExtensions]]에서 정의된 대로 설정합니다.

    6. instance.[[OwnPropertyKeys]]를 § 3.9.6 [[OwnPropertyKeys]]에서 정의된 대로 설정합니다.

  14. instance를 반환합니다.

글로벌 프로퍼티 참조 정의하기: target에 대해 realm realm을 전달받아 다음 단계를 수행합니다:
  1. interfaces를 목록으로 하여, realm에 노출된 모든 인터페이스를 포함시킵니다.

  2. interfaces를 정렬합니다. 만약 interfaces의 항목 A와 B에 대해, A가 상속받았다면, A의 인덱스가 B보다 높게 정렬합니다.

  3. 각 interface에 대해 interfaces에서:

    1. interface가 [LegacyNoInterfaceObject] 또는 [LegacyNamespace] 확장 속성으로 선언되지 않았다면:

      1. id를 interface의 식별자로 설정합니다.

      2. interfaceObject를 인터페이스 객체 생성 알고리즘을 interface, id, realm에 대해 실행한 결과로 설정합니다.

      3. DefineMethodProperty(target, id, interfaceObject, false)를 실행합니다.

      4. interface가 [LegacyWindowAlias] 확장 속성으로 선언되어 있고, target이 Window 인터페이스를 구현하고 있다면:

        1. 각 [LegacyWindowAlias]의 식별자들에 포함된 식별자 id에 대해:

          1. DefineMethodProperty(target, id, interfaceObject, false)를 실행합니다.

    2. interface가 [LegacyFactoryFunction] 확장 속성으로 선언되었다면:

      1. 각 [LegacyFactoryFunction]의 식별자들에 포함된 식별자 id에 대해:

        1. legacyFactoryFunction을 레거시 팩토리 함수 생성 알고리즘을 id, interface, realm에 대해 실행한 결과로 설정합니다.

        2. DefineMethodProperty(target, id, legacyFactoryFunction, false)를 실행합니다.

  4. 각 콜백 인터페이스 interface에 대해, realm에 노출되고, 상수가 정의되어 있는 경우:

    1. id를 interface의 식별자로 설정합니다.

    2. interfaceObject를 레거시 콜백 인터페이스 객체 생성 알고리즘을 interface, id, realm에 대해 실행한 결과로 설정합니다.

    3. DefineMethodProperty(target, id, interfaceObject, false)를 실행합니다.

  5. 각 네임스페이스 namespace에 대해, realm에 노출된 경우:

    1. id를 namespace의 식별자로 설정합니다.

    2. namespaceObject를 네임스페이스 객체 생성 알고리즘을 namespace, realm에 대해 실행한 결과로 설정합니다.

    3. DefineMethodProperty(target, id, namespaceObject, false)를 실행합니다.

플랫폼 객체가 구현하는 인터페이스 집합은 객체의 생명주기 동안 변하지 않습니다.

서로 다른 플랫폼 객체가 서로 다른 글로벌 객체를 가지더라도, [[PrimaryInterface]] 내부 슬롯에 같은 인터페이스를 참조할 수 있습니다. 예를 들어, 같은 오리진의 iframe이 있고, iframe의 메서드가 메인 페이지의 같은 종류의 요소에 호출되어도 예외가 발생하지 않습니다.

인터페이스 믹스인은 구현 알고리즘 평가에 직접 참여하지 않습니다. 대신, 인터페이스 믹스인이 포함된 각 인터페이스는 믹스인의 각 멤버에 대해 자신의 "복사본"을 가지며, 해당 operation function은 수신자가 구현하는 인터페이스가 믹스인을 포함하는지 확인합니다.

플랫폼 객체의 주 인터페이스(primary interface)는 객체의 [[PrimaryInterface]] 내부 슬롯 값입니다. 이는 해당 객체가 구현하는 가장 파생된 인터페이스입니다.

플랫폼 객체가 연관된 realm은 객체 생성 후 변경될 수 있습니다. 플랫폼 객체에 연관된 realm이 변경되면, [[Prototype]] 내부 슬롯은 즉시 해당 플랫폼 객체의 새 realm의 주 인터페이스의 인터페이스 프로토타입 객체로 업데이트되어야 합니다.

또한, [Global] 확장 속성을 가진 인터페이스를 구현하는 플랫폼 객체는 다음에서 선언적으로 프로퍼티를 얻습니다:

대신 그 프로퍼티들을 명령형으로 정의해야 합니다.

3.8.1. [[SetPrototypeOf]]

[[SetPrototypeOf]] 내부 메서드가 플랫폼 객체 O에 대해 호출되며, O가 인터페이스를 구현하고 그 인터페이스에 [Global] 확장 속성이 있으며 JavaScript 언어 값 V로 호출되면, 다음 단계를 수행합니다:

  1. O의 연관된 realm의 글로벌 프로토타입 체인이 변경 가능 이 true이면, ? OrdinarySetPrototypeOf(O, V)를 반환합니다.

  2. ? SetImmutablePrototype(O, V)를 반환합니다.

참고: Window 객체의 경우, WindowProxy 객체의 존재로 인해 [[SetPrototypeOf]]가 Window 객체에 직접 호출되는 것이 관찰되지 않으므로 이 구현 여부는 관찰 불가합니다. 그러나 다른 글로벌 객체의 경우에는 필요합니다.

3.9. 레거시 플랫폼 객체

레거시 플랫폼 객체는 자신의 인덱스 프로퍼티와 이름 프로퍼티에 해당하는 추가 프로퍼티를 갖는 것처럼 보입니다. 이러한 프로퍼티는 객체의 실제 own 프로퍼티가 아니지만, [[GetOwnProperty]] 내부 메서드를 통해 노출되어 객체의 own 프로퍼티처럼 동작합니다.

하나의 객체가 인덱스 프로퍼티를 지원하는 여러 인터페이스를 구현하는 것이 허용됩니다. 그러나 이 경우, 객체의 지원되는 프로퍼티 인덱스에 대해 정의가 충돌한다면, 객체가 어떤 추가 프로퍼티를 갖는지, 인덱스 프로퍼티와 관련한 정확한 동작은 정의되지 않습니다. 이름 프로퍼티도 마찬가지입니다.

파생된 인터페이스에서 정의된 인덱스 프로퍼티 getter가 레거시 플랫폼 객체가 구현하는 인터페이스 중 가장 파생된 인터페이스의 동작을 정의합니다. 객체를 배열 인덱스로 인덱싱할 때 해당 getter가 동작합니다. 인덱스 프로퍼티 setter도 마찬가지로 가장 파생된 인터페이스의 정의를 따릅니다. 이렇게 하면 상위 인터페이스의 특수 연산 정의가 오버라이드될 수 있습니다.

프로퍼티 이름 O가 구현하는 인터페이스 중 어떤 인터페이스의 인터페이스 멤버가 해당 식별자로 존재하고, 그 인터페이스 멤버가 해당 인터페이스들 중 하나에서 위조 불가(unforgeable)일 경우, 해당 플랫폼 객체 O의 위조 불가 프로퍼티 이름이 됩니다.

getter 지원은 § 3.9.1 [[GetOwnProperty]]에서, setter 지원은 § 3.9.3 [[DefineOwnProperty]] 및 § 3.9.2 [[Set]]에서 처리됩니다.

또한, 레거시 플랫폼 객체는 다음에서 정의된 내부 메서드를 갖습니다:

3.9.1. [[GetOwnProperty]]

모든 레거시 플랫폼 객체 O의 [[GetOwnProperty]] 내부 메서드는 프로퍼티 이름 P로 호출될 때 다음과 같이 동작해야 합니다:

  1. ? LegacyPlatformObjectGetOwnProperty(O, P, false)를 반환합니다.

3.9.2. [[Set]]

모든 레거시 플랫폼 객체 O의 [[Set]] 내부 메서드는 프로퍼티 이름 P, 값 V, 자바스크립트 값 Receiver로 호출될 때 다음과 같이 동작해야 합니다:

  1. O와 Receiver가 같은 객체라면:

    1. O가 인덱스 프로퍼티 setter가 있는 인터페이스를 구현하고, P가 배열 인덱스라면:

      1. 인덱스 프로퍼티 setter 호출을 O에 P와 V로 실행합니다.

      2. true를 반환합니다.

    2. O가 이름 프로퍼티 setter가 있는 인터페이스를 구현하고, P가 문자열(String)이라면:

      1. 이름 프로퍼티 setter 호출을 O에 P와 V로 실행합니다.

      2. true를 반환합니다.

  2. ownDesc를 ? LegacyPlatformObjectGetOwnProperty(O, P, true)의 결과로 설정합니다.

  3. ? OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc)를 수행합니다.

3.9.3. [[DefineOwnProperty]]

레거시 플랫폼 객체 O의 [[DefineOwnProperty]] 내부 메서드는 프로퍼티 키 P와 프로퍼티 디스크립터(Property Descriptor) Desc로 호출될 때 다음 단계를 수행해야 합니다:

  1. O가 인덱스 프로퍼티를 지원하고 P가 배열 인덱스라면:

    1. IsDataDescriptor(Desc)의 결과가 false라면 false를 반환합니다.

    2. O가 인덱스 프로퍼티 setter가 있는 인터페이스를 구현하지 않는다면 false를 반환합니다.

    3. 인덱스 프로퍼티 setter 호출을 O에 P와 Desc.[[Value]]로 실행합니다.

    4. true를 반환합니다.

  2. O가 명명된 속성을 지원하고, O가 [Global] 확장 속성이 있는 인터페이스를 구현하지 않으며, P가 String이고, P가 O의 위조 불가능한 속성 이름이 아니면:

    1. P가 지원되는 속성 이름이 아니면 creating을 true로, 그렇지 않으면 false로 둡니다.

    2. O가 [LegacyOverrideBuiltIns] 확장 속성이 있는 인터페이스를 구현하거나, O가 P라는 이름의 고유 속성을 갖지 않으면:

      1. creating이 false이고 O가 명명된 속성 setter가 있는 인터페이스를 구현하지 않으면, false를 반환합니다.

      2. O가 구현하는 인터페이스에 명명된 속성 setter가 있으면:

        1. IsDataDescriptor(Desc)를 호출한 결과가 false이면, false를 반환합니다.

        2. P와 Desc.[[Value]]를 사용하여 O에서 명명된 속성 setter를 호출합니다.

        3. true를 반환합니다.

  3. ! OrdinaryDefineOwnProperty(O, P, Desc)를 반환합니다.

3.9.4. [[Delete]]

모든 레거시 플랫폼 객체 O의 [[Delete]] 내부 메서드는 속성 이름 P로 호출될 때 다음과 같이 동작해야 합니다.

  1. O가 인덱스 속성을 지원하고 P가 배열 인덱스이면:

    1. index를 ! ToUint32(P)를 호출한 결과로 둡니다.

    2. index가 지원되는 속성 인덱스가 아니면, true를 반환합니다.

    3. false를 반환합니다.

  2. O가 명명된 속성을 지원하고, O가 [Global] 확장 속성이 있는 인터페이스를 구현하지 않으며 속성 이름 P와 객체 O로 명명된 속성 가시성 알고리즘을 호출한 결과가 true이면:

    1. O가 명명된 속성 삭제자가 있는 인터페이스를 구현하지 않으면, false를 반환합니다.

    2. operation을 명명된 속성 삭제자를 선언하는 데 사용된 연산으로 둡니다.

    3. operation이 식별자 없이 정의되었다면:

      1. 인터페이스 설명에 나열된 단계를 수행하여 기존 명명된 속성을 삭제합니다. 이때 P를 이름으로 사용합니다.

      2. 단계에서 삭제가 실패했다고 나타내면, false를 반환합니다.

    4. 그렇지 않으면, operation은 식별자와 함께 정의되었습니다:

      1. operation의 메서드 단계를 수행하되, O를 this로, « P »를 인수 값으로 사용합니다.

      2. operation이 반환 타입을 boolean으로 선언했고 단계가 false를 반환했다면, false를 반환합니다.

    5. true를 반환합니다.

  3. O에 이름이 P인 고유 속성이 있으면:

    1. 속성을 구성할 수 없으면, false를 반환합니다.

    2. 그렇지 않으면, O에서 해당 속성을 제거합니다.

  4. true를 반환합니다.

3.9.5. [[PreventExtensions]]

레거시 플랫폼 객체의 [[PreventExtensions]] 내부 메서드가 호출될 때, 다음 단계를 수행합니다:

  1. false를 반환합니다.

참고: 이렇게 하면 레거시 플랫폼 객체가 [[PreventExtensions]]가 실패하도록 만들어 계속 확장 가능하게 유지됩니다.

3.9.6. [[OwnPropertyKeys]]

이 문서는 플랫폼 객체가 인터페이스를 구현할 때 (또는 예외를 나타내는 플랫폼 객체에 대해) 전체 프로퍼티 열거 순서를 정의하지 않습니다. 그러나 레거시 플랫폼 객체에 대해서는 아래와 같이 [[OwnPropertyKeys]] 내부 메서드를 정의합니다.

레거시 플랫폼 객체 O의 [[OwnPropertyKeys]] 내부 메서드가 호출될 때, 다음 단계를 수행합니다:

  1. keys를 자바스크립트 String과 Symbol 값의 빈 목록으로 생성합니다.

  2. O가 인덱스 프로퍼티를 지원하면, 각 O의 지원되는 프로퍼티 인덱스 index에 대해, 숫자 오름차순으로 append ! ToString(index)을 keys에 추가합니다.

  3. O가 이름 프로퍼티를 지원하면, 각 O의 지원되는 프로퍼티 이름 P 중 이름 프로퍼티 가시성 알고리즘에 따라 visible한 것에 대해, append P를 keys에 추가합니다.

  4. 각 O의 own 프로퍼티 키 중 String 타입 P에 대해, 프로퍼티 생성 시간 오름차순으로 append P를 keys에 추가합니다.

  5. 각 O의 own 프로퍼티 키 중 Symbol 타입 P에 대해, 프로퍼티 생성 시간 오름차순으로 append P를 keys에 추가합니다.

  6. 단언: keys에는 중복 항목이 없다.

  7. keys를 반환합니다.

3.9.7. 추상 연산

프로퍼티 이름 P가 배열 인덱스인지 판단하기 위해, 다음 알고리즘을 적용한다:

  1. P가 문자열이 아니면 false를 반환합니다.

  2. index를 CanonicalNumericIndexString(P)의 결과로 설정합니다.

  3. index가 undefined이면 false를 반환합니다.

  4. IsInteger(index)가 false이면 false를 반환합니다.

  5. index가 −0이면 false를 반환합니다.

  6. index < 0이면 false를 반환합니다.

  7. index ≥ 232 − 1이면 false를 반환합니다.

    참고: 232 − 1은 자바스크립트에서 허용되는 최대 배열 길이입니다.

  8. true를 반환합니다.

명명된 속성 가시성 알고리즘은 주어진 명명된 속성이 객체에 노출되는지 여부를 결정하는 데 사용됩니다. 일부 명명된 속성은 [LegacyOverrideBuiltIns] 확장 속성이 사용되었는지에 따라 객체에 노출되지 않습니다. 알고리즘은 속성 이름 P와 객체 O를 사용하여 다음과 같이 동작합니다:

  1. P가 O의 지원되는 속성 이름이 아니면, false를 반환합니다.

  2. O에 이름이 P인 고유 속성이 있으면, false를 반환합니다.

    참고: 여기에는 O에 위조 불가능한 속성이 있는 경우도 포함됩니다. 실제로 이러한 속성은 객체에 지원되는 속성 이름이 생기기 전에 항상 설정되며, 일단 설정되면 해당 명명된 속성이 보이지 않게 되기 때문입니다.

  3. O가 [LegacyOverrideBuiltIns] 확장 속성이 있는 인터페이스를 구현하면, true를 반환합니다.

  4. prototype을 O.[[GetPrototypeOf]]()로 둡니다.

  5. prototype이 null이 아닌 동안:

    1. prototype이 명명된 속성 객체가 아니고, prototype에 이름이 P인 고유 속성이 있으면, false를 반환합니다.

    2. prototype을 prototype.[[GetPrototypeOf]]()로 설정합니다.

  6. true를 반환합니다.

이 알고리즘은 이름 프로퍼티를 가진 객체의 프로퍼티 해석 순서가 다음과 같이 이루어지도록 보장합니다:

  1. 인덱스 프로퍼티.

  2. own 프로퍼티(위조 불가 속성과 연산 포함).

  3. [LegacyOverrideBuiltIns]이 지정된 경우:

    1. 이름 프로퍼티.

    2. 프로토타입 체인에서 오는 프로퍼티.

  4. [LegacyOverrideBuiltIns]이 없는 경우:

    1. 프로토타입 체인에서 오는 프로퍼티.

    2. 이름 프로퍼티.

플랫폼 객체 O에서 프로퍼티 이름 P와 자바스크립트 값 V로 인덱스 프로퍼티 setter 호출을 하려면 다음 단계를 수행합니다:

  1. index를 ? ToUint32(P)로 설정합니다.

  2. index가 지원되는 프로퍼티 인덱스가 아니면 creating을 true로, 그렇지 않으면 false로 설정합니다.

  3. operation을 인덱스 프로퍼티 setter를 선언한 operation으로 설정합니다.

  4. T를 operation의 두 번째 인자의 타입으로 설정합니다.

  5. value를 V를 T 타입의 IDL 값으로 변환한 결과로 설정합니다.

  6. operation이 식별자 없이 정의되어 있다면:

    1. creating이 true이면 인터페이스 설명에 따라 새 인덱스 프로퍼티 값 설정 단계(인덱스 index, 값 value)를 수행합니다.

    2. 그 외의 경우(creating이 false) 인터페이스 설명에 따라 기존 인덱스 프로퍼티 값 설정 단계(인덱스 index, 값 value)를 수행합니다.

  7. 그 외의 경우, operation이 식별자와 함께 정의되어 있다면 메서드 단계를 operation에 대해 O를 this로, 인자값 « index, value »로 실행합니다.

플랫폼 객체 O에서 프로퍼티 이름 P와 자바스크립트 값 V로 이름 프로퍼티 setter 호출을 하려면 다음 단계를 수행합니다:

  1. creating을 P가 지원되는 프로퍼티 이름이 아니면 true로, 그렇지 않으면 false로 설정합니다.

  2. operation을 이름 프로퍼티 setter를 선언한 operation으로 설정합니다.

  3. T를 operation의 두 번째 인자의 타입으로 설정합니다.

  4. value를 V를 T 타입의 IDL 값으로 변환한 결과로 설정합니다.

  5. operation이 식별자 없이 정의되어 있다면:

    1. creating이 true이면 인터페이스 설명에 따라 새 이름 프로퍼티 값 설정 단계(P, value)를 수행합니다.

    2. 그 외의 경우(creating이 false) 인터페이스 설명에 따라 기존 이름 프로퍼티 값 설정 단계(P, value)를 수행합니다.

  6. 그 외의 경우, operation이 식별자와 함께 정의되어 있다면 메서드 단계를 operation에 대해 O를 this로, 인자값 « P, value »로 실행합니다.

LegacyPlatformObjectGetOwnProperty 추상 연산은 객체 O, 프로퍼티 이름 P, 불리언 ignoreNamedProps 값을 받아 다음 단계를 수행합니다:

  1. O가 인덱스 프로퍼티를 지원하고, P가 배열 인덱스라면:

    1. index를 ! ToUint32(P)로 설정합니다.

    2. index가 지원되는 프로퍼티 인덱스라면:

      1. operation을 인덱스 프로퍼티 getter를 선언한 operation으로 설정합니다.

      2. value를 초기화되지 않은 변수로 설정합니다.

      3. operation이 식별자 없이 정의되어 있다면 value를 인터페이스 설명에 따라 인덱스 프로퍼티 값 결정(index)의 결과로 설정합니다.

      4. 그 외의 경우, operation이 식별자와 함께 정의되어 있다면 value를 메서드 단계를 operation에 대해 O를 this로, 인자값 « index »로 실행한 결과로 설정합니다.

      5. desc를 필드가 없는 새로운 프로퍼티 디스크립터(Property Descriptor)로 생성합니다.

      6. desc.[[Value]]를 value를 자바스크립트 값으로 변환한 결과로 설정합니다.

      7. O가 인덱스 프로퍼티 setter가 있는 인터페이스를 구현하면 desc.[[Writable]]을 true로, 그렇지 않으면 false로 설정합니다.

      8. desc.[[Enumerable]] 및 desc.[[Configurable]]을 true로 설정합니다.

      9. desc를 반환합니다.

    3. ignoreNamedProps를 true로 설정합니다.

  2. O가 이름 프로퍼티를 지원하고, ignoreNamedProps가 false이면:

    1. 이름 프로퍼티 가시성 알고리즘을 프로퍼티 이름 P와 객체 O로 실행한 결과가 true이면:

      1. operation을 이름 프로퍼티 getter를 선언한 operation으로 설정합니다.

      2. value를 초기화되지 않은 변수로 설정합니다.

      3. operation이 식별자 없이 정의되어 있다면 value를 인터페이스 설명에 따라 이름 프로퍼티 값 결정(P)의 결과로 설정합니다.

      4. 그 외의 경우, operation이 식별자와 함께 정의되어 있다면 value를 메서드 단계를 operation에 대해 O를 this로, 인자값 « P »로 실행한 결과로 설정합니다.

      5. desc를 필드가 없는 새로운 프로퍼티 디스크립터(Property Descriptor)로 생성합니다.

      6. desc.[[Value]]를 value를 자바스크립트 값으로 변환한 결과로 설정합니다.

      7. O가 이름 프로퍼티 setter가 있는 인터페이스를 구현하면 desc.[[Writable]]을 true로, 그렇지 않으면 false로 설정합니다.

      8. O가 [LegacyUnenumerableNamedProperties] 확장 속성이 있는 인터페이스를 구현하면 desc.[[Enumerable]]을 false로, 그렇지 않으면 true로 설정합니다.

      9. desc.[[Configurable]]을 true로 설정합니다.

      10. desc를 반환합니다.

  3. OrdinaryGetOwnProperty(O, P)를 반환합니다.

3.10. 관찰 가능한 배열 이그조틱 객체

관찰 가능한 배열 이그조틱 객체는 자바스크립트의 프록시(Proxy) 이그조틱 객체의 한 종류로, 이 절에서 정의된 프록시 트랩을 사용해 생성됩니다. 자바스크립트 명세는 프록시 이그조틱 객체가 Array 인스턴스를 프록시 대상으로 가질 때 특별 처리를 포함하므로, 관찰 가능한 배열 타입이 자바스크립트 코드에 이러한 특별 처리가 유지된 채 노출되도록 하기 위해 이렇게 정의합니다.

관찰 가능한 배열 이그조틱 객체의 프록시 트랩은 일반 Array 인스턴스의 불변성 외에도 다음의 불변성을 보장합니다:

관찰 가능한 배열 이그조틱 객체 생성하기: realm realm에서 Web IDL 타입 T와 알고리즘 setAlgorithm, deleteAlgorithm이 주어졌을 때:
  1. innerArray를 ! ArrayCreate(0)으로 둔다.

  2. handler를 OrdinaryObjectCreate(null, « [[Type]], [[SetAlgorithm]], [[DeleteAlgorithm]], [[BackingList]] »)로 둔다.

  3. handler.[[Type]]을 T로 설정한다.

  4. handler.[[SetAlgorithm]]을 setAlgorithm으로 설정한다.

  5. handler.[[DeleteAlgorithm]]을 deleteAlgorithm으로 설정한다.

  6. defineProperty를 CreateBuiltinFunction(§ 3.10.1 defineProperty의 단계, 3, "", « », realm)로 둔다.

  7. ! CreateDataPropertyOrThrow(handler, "defineProperty", defineProperty)를 실행한다.

  8. deleteProperty를 CreateBuiltinFunction(§ 3.10.2 deleteProperty의 단계, 2, "", « », realm)로 둔다.

  9. ! CreateDataPropertyOrThrow(handler, "deleteProperty", deleteProperty)를 실행한다.

  10. get을 CreateBuiltinFunction(§ 3.10.3 get의 단계, 3, "", « », realm)로 둔다.

  11. ! CreateDataPropertyOrThrow(handler, "get", get)을 실행한다.

  12. getOwnPropertyDescriptor를 CreateBuiltinFunction(§ 3.10.4 getOwnPropertyDescriptor의 단계, 2, "", « », realm)로 둔다.

  13. ! CreateDataPropertyOrThrow(handler, "getOwnPropertyDescriptor", getOwnPropertyDescriptor)를 실행한다.

  14. has를 CreateBuiltinFunction(§ 3.10.5 has의 단계, 2, "", « », realm)로 둔다.

  15. ! CreateDataPropertyOrThrow(handler, "has", has)를 실행한다.

  16. ownKeys를 CreateBuiltinFunction(§ 3.10.6 ownKeys의 단계, 1, "", « », realm)로 둔다.

  17. ! CreateDataPropertyOrThrow(handler, "ownKeys", ownKeys)를 실행한다.

  18. preventExtensions를 CreateBuiltinFunction(§ 3.10.7 preventExtensions의 단계, « », 0, "", realm)로 둔다.

  19. ! CreateDataPropertyOrThrow(handler, "preventExtensions", preventExtensions)를 실행한다.

  20. set을 CreateBuiltinFunction(§ 3.10.8 set의 단계, « », 4, "", realm)로 둔다.

  21. ! CreateDataPropertyOrThrow(handler, "set", set)을 실행한다.

  22. ! ProxyCreate(innerArray, handler)를 반환한다.

3.10.1. defineProperty

defineProperty 프록시 트랩의 단계(관찰 가능한 배열 이그조틱 객체에 대해, O, P, descriptorObj가 주어진 경우):
  1. handler를 this 값으로 설정합니다.

  2. descriptor를 ! ToPropertyDescriptor(descriptorObj)로 설정합니다.

  3. P가 "length"이면:

    1. IsAccessorDescriptor(descriptor) 값이 true이면 false를 반환합니다.

    2. descriptor.[[Configurable]]가 존재하고 값이 true이면 false를 반환합니다.

    3. descriptor.[[Enumerable]]가 존재하고 값이 true이면 false를 반환합니다.

    4. descriptor.[[Writable]]가 존재하고 값이 false이면 false를 반환합니다.

    5. descriptor.[[Value]]가 존재하면 길이 설정 알고리즘을 handler, descriptor.[[Value]]로 실행한 결과를 반환합니다.

    6. true를 반환합니다.

  4. P가 배열 인덱스이면:

    1. IsAccessorDescriptor(descriptor) 값이 true이면 false를 반환합니다.

    2. descriptor.[[Configurable]]가 존재하고 값이 false이면 false를 반환합니다.

    3. descriptor.[[Enumerable]]가 존재하고 값이 false이면 false를 반환합니다.

    4. descriptor.[[Writable]]가 존재하고 값이 false이면 false를 반환합니다.

    5. descriptor.[[Value]]가 존재하면 인덱스 값 설정 알고리즘을 handler, P, descriptor.[[Value]]로 실행한 결과를 반환합니다.

    6. true를 반환합니다.

  5. ? O.[[DefineOwnProperty]](P, descriptor)를 반환합니다.

3.10.2. deleteProperty

deleteProperty 프록시 트랩의 단계(관찰 가능한 배열 이그조틱 객체에 대해, O, P가 주어진 경우):
  1. handler를 this 값으로 설정합니다.

  2. P가 "length"이면 false를 반환합니다.

  3. P가 배열 인덱스이면:

    1. oldLen을 handler.[[BackingList]]의 크기로 설정합니다.

    2. index를 ! ToUint32(P)로 설정합니다.

    3. index ≠ oldLen − 1이면 false를 반환합니다.

    4. handler.[[DeleteAlgorithm]] 알고리즘 단계를 handler.[[BackingList]][index]와 index로 실행합니다.

    5. handler.[[BackingList]]의 마지막 아이템을 제거합니다.

    6. true를 반환합니다.

  4. ? O.[[Delete]](P)를 반환합니다.

3.10.3. get

get 프록시 트랩의 단계(관찰 가능한 배열 이그조틱 객체에 대해, O, P, Receiver가 주어진 경우):
  1. handler를 this 값으로 설정합니다.

  2. length를 handler.[[BackingList]]의 크기로 설정합니다.

  3. P가 "length"이면 length를 반환합니다.

  4. P가 배열 인덱스이면:

    1. index를 ! ToUint32(P)로 설정합니다.

    2. index ≥ length이면 undefined를 반환합니다.

    3. jsValue를 변환 하여 얻은 handler.[[BackingList]][index]의 JavaScript 값으로 한다.

    4. 위 단계는 절대 예외를 발생시키지 않습니다.

    5. jsValue를 반환합니다.

  5. ? O.[[Get]](P, Receiver)를 반환합니다.

3.10.4. getOwnPropertyDescriptor

getOwnPropertyDescriptor 프록시 트랩의 단계(관찰 가능한 배열 이그조틱 객체에 대해, O, P가 주어진 경우):
  1. handler를 this 값으로 설정합니다.

  2. length를 handler.[[BackingList]]의 크기로 설정합니다.

  3. P가 "length"이면 ! FromPropertyDescriptor(PropertyDescriptor{[[Configurable]]: false, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: length })를 반환합니다.

  4. P가 배열 인덱스이면

    1. index를 ! ToUint32(P)로 설정합니다.

    2. index ≥ length이면 undefined를 반환합니다.

    3. jsValue를 변환 하여 얻은 handler.[[BackingList]][index]의 JavaScript 값으로 한다.

    4. 위 단계는 절대 예외를 발생시키지 않습니다.

    5. FromPropertyDescriptor(PropertyDescriptor{[[Configurable]]: true, [[Enumerable]]: true, [[Writable]]: true, [[Value]]: jsValue })를 반환합니다.

  5. FromPropertyDescriptor(? O.[[GetOwnProperty]](P))를 반환합니다.

3.10.5. has

has 프록시 트랩의 단계(관찰 가능한 배열 이그조틱 객체에 대해, O, P가 주어진 경우):
  1. handler를 this 값으로 설정합니다.

  2. P가 "length"이면 true를 반환합니다.

  3. P가 배열 인덱스이면:

    1. index를 ! ToUint32(P)로 설정합니다.

    2. index가 handler.[[BackingList]]의 크기보다 작으면 true를 반환합니다.

    3. false를 반환합니다.

  4. ? O.[[HasProperty]](P)를 반환합니다.

3.10.6. ownKeys

ownKeys 프록시 트랩의 단계(관찰 가능한 배열 이그조틱 객체에 대해, O가 주어진 경우):
  1. handler를 this 값으로 설정합니다.

  2. length를 handler.[[BackingList]]의 크기로 설정합니다.

  3. keys를 빈 목록으로 설정합니다.

  4. i를 0으로 설정합니다.

  5. While i < length 동안:

    1. keys에 ! ToString(i)를 추가합니다.

    2. i를 i + 1로 설정합니다.

  6. keys에 ! O.[[OwnPropertyKeys]]()를 확장합니다.

  7. CreateArrayFromList(keys)를 반환합니다.

3.10.7. preventExtensions

preventExtensions 프록시 트랩의 단계(관찰 가능한 배열 이그조틱 객체에 대해):
  1. false를 반환합니다.

3.10.8. set

set 프록시 트랩의 단계(관찰 가능한 배열 이그조틱 객체에 대해, O, P, V, Receiver가 주어진 경우):
  1. handler를 this 값으로 설정합니다.

  2. P가 "length"이면 길이 설정 알고리즘을 handler, V로 실행한 결과를 반환합니다.

  3. P가 배열 인덱스이면 인덱스 값 설정 알고리즘을 handler, P, V로 실행한 결과를 반환합니다.

  4. ? O.[[Set]](P, V, Receiver)를 반환합니다.

3.10.9. 추상 연산

길이 설정 알고리즘(관찰 가능한 배열 이그조틱 객체의 handler와 newLen이 주어진 경우):
  1. uint32Len을 ? ToUint32(newLen)로 설정합니다.

  2. numberLen을 ? ToNumber(newLen)로 설정합니다.

  3. uint32Len ≠ numberLen이면 RangeError 예외를 throw합니다.

  4. oldLen을 handler.[[BackingList]]의 크기로 설정합니다.

  5. uint32Len > oldLen이면 false를 반환합니다.

  6. indexToDelete를 oldLen − 1로 설정합니다.

  7. While indexToDelete ≥ uint32Len 동안:

    1. handler.[[DeleteAlgorithm]] 알고리즘 단계를 handler.[[BackingList]][indexToDelete]와 indexToDelete로 실행합니다.

    2. handler.[[BackingList]]의 마지막 아이템을 제거합니다.

    3. indexToDelete를 indexToDelete − 1로 설정합니다.

  8. true를 반환합니다.

인덱스 값 설정 알고리즘(관찰 가능한 배열 이그조틱 객체의 handler, P, V가 주어진 경우):
  1. oldLen을 handler.[[BackingList]]의 크기로 설정합니다.

  2. index를 ! ToUint32(P)로 설정합니다.

  3. index > oldLen이면 false를 반환합니다.

  4. idlValue를 V를 handler.[[Type]] 타입의 IDL 값으로 변환한 결과로 설정합니다.

  5. index < oldLen이면:

    1. handler.[[DeleteAlgorithm]] 알고리즘 단계를 handler.[[BackingList]][index]와 index로 실행합니다.

  6. handler.[[SetAlgorithm]] 알고리즘 단계를 idlValue와 index로 실행합니다.

  7. index = oldLen이면 idlValue를 handler.[[BackingList]]에 추가합니다.

  8. 그 외의 경우, handler.[[BackingList]][index]를 idlValue로 설정합니다.

  9. true를 반환합니다.

3.11. 콜백 인터페이스

§ 2.12 인터페이스를 구현하는 객체에서 설명한 것처럼, 콜백 인터페이스는 스크립트에서 임의의 자바스크립트 객체로 구현될 수 있습니다. 아래의 경우들은 주어진 객체에서 콜백 인터페이스의 연산이 어떻게 호출되는지 설명합니다:

자바스크립트 객체는 해당 객체가 콜백 인터페이스를 구현하는 것으로 간주되기 위해 그 인터페이스에 선언된 상수에 해당하는 프로퍼티를 가질 필요가 없습니다.

Web IDL 인자 리스트란 각 값이 IDL 값이거나 “누락(missing)”이라는 특수 값(선택적 인자가 누락됨을 나타냄)인 값 목록(list)입니다.

Web IDL 인자 리스트를 자바스크립트 인자 리스트로 변환하기: Web IDL 인자 리스트 args가 주어졌을 때, 다음 단계를 수행합니다:
  1. jsArgs를 빈 목록으로 생성합니다.

  2. i를 0으로 설정합니다.

  3. count를 0으로 설정합니다.

  4. i < args의 크기인 동안:

    1. args[i]가 특수 값 “missing”이면, jsArgs에 undefined를 추가합니다.

    2. 그 외의 경우, args[i]는 IDL 값입니다:

      1. convertResult를 args[i]를 자바스크립트 값으로 변환한 결과로 설정합니다. 예외가 발생하면 다시 throw합니다.

      2. convertResult를 jsArgs에 추가합니다.

      3. count를 i + 1로 설정합니다.

    3. i를 i + 1로 설정합니다.

  5. jsArgs를 count 개의 항목만 남도록 잘라냅니다.

  6. jsArgs를 반환합니다.

사용자 객체의 연산 호출하기: 콜백 인터페이스 타입 값 value, 연산 이름 opName, Web IDL 인자 리스트 args, 선택적 콜백 this 값 thisArg가 주어졌을 때, 다음 단계를 수행합니다. 이 단계들은 IDL 값을 반환하거나 예외를 throw합니다.

  1. completion을 초기화되지 않은 변수로 설정합니다.

  2. thisArg가 주어지지 않았다면 thisArg를 undefined로 설정합니다.

  3. O를 value에 해당하는 자바스크립트 객체로 설정합니다.

  4. realm을 O의 연결된 realm으로 설정합니다.

  5. relevant settings를 realm의 설정 객체(settings object)로 설정합니다.

  6. stored settings를 value의 콜백 컨텍스트로 설정합니다.

  7. 스크립트 실행 준비를 relevant settings로 실행합니다.

  8. 콜백 실행 준비를 stored settings로 실행합니다.

  9. X를 O로 설정합니다.

  10. IsCallable(O)가 false이면:

    1. getResult를 Completion(Get(O, opName))로 설정합니다.

    2. getResult가 비정상 완료(abrupt completion)이면, completion에 getResult를 할당하고 return 단계로 점프합니다.

    3. X를 getResult.[[Value]]로 설정합니다.

    4. IsCallable(X)가 false이면, completion을 Completion Record { [[Type]]: throw, [[Value]]: 새로 생성된 TypeError 객체, [[Target]]: 빈 값 }로 설정하고 return 단계로 점프합니다.

    5. thisArg를 O로 설정합니다(주어진 값을 덮어씀).

  11. jsArgs를 args를 자바스크립트 인자 리스트로 변환한 결과로 설정합니다. 변환 중 예외 발생 시, completion을 예외를 나타내는 completion 값으로 설정하고 return 단계로 점프합니다.

  12. callResult를 Completion(Call(X, thisArg, jsArgs))로 설정합니다.

  13. callResult가 비정상 완료(abrupt completion)이면 completion에 callResult를 할당하고 return 단계로 점프합니다.

  14. completion을 callResult.[[Value]]를 연산의 반환 타입과 동일한 타입의 IDL 값으로 변환한 결과로 설정합니다. 변환 중 예외 발생 시 completion을 예외를 나타내는 completion 값으로 설정합니다.

  15. Return: 이 시점에서 completion은 IDL 값이거나 비정상 완료임.

    1. 콜백 실행 후 정리(clean up)를 stored settings로 실행합니다.

    2. 스크립트 실행 후 정리(clean up)를 relevant settings로 실행합니다.

    3. completion이 IDL 값이면 completion을 반환합니다.

    4. completion이 비정상 완료이고, 연산이 반환 타입이 프라미스 타입이 아닌 경우, completion.[[Value]]를 throw합니다.

    5. rejectedPromise를 ! Call(%Promise.reject%, %Promise%, «completion.[[Value]]»)로 설정합니다.

    6. rejectedPromise를 연산의 반환 타입으로 변환한 결과를 반환합니다.

3.11.1. 레거시 콜백 인터페이스 객체

특정 콜백 인터페이스가 특정 realm에 노출되고, 해당 인터페이스에 상수가 정의되어 있다면, 대응하는 프로퍼티가 그 realm의 글로벌 객체에 존재합니다. 프로퍼티 이름은 해당 콜백 인터페이스의 식별자이며, 그 값은 레거시 콜백 인터페이스 객체입니다.

특정 콜백 인터페이스에 대한 레거시 콜백 인터페이스 객체는 내장 함수 객체입니다. 해당 객체에는 그 인터페이스에 정의된 상수에 대응하는 프로퍼티가 있습니다. 자세한 내용은 § 3.7.5 상수 참고.

참고: 레거시 콜백 인터페이스 객체는 함수 객체이므로, typeof 연산자를 레거시 콜백 인터페이스 객체에 적용하면 "function"이 반환됩니다.

특정 콜백 인터페이스 interface 에 대해 식별자 id 와 realm realm 이 주어졌을 때, 레거시 콜백 인터페이스 객체 를 생성 하는 절차는 다음과 같습니다:

  1. steps를 다음 단계로 둔다:

    1. 예외를 발생시킨다(throw) TypeError.

  2. F를 CreateBuiltinFunction(steps, 0, id, « », realm)의 결과로 둔다.

  3. 상수 정의를 interface와 F, realm에 대해 수행한다.

  4. F를 반환한다.

3.12. 콜백 함수 호출하기

자바스크립트 호출 가능(callable) 객체가 콜백 함수 값으로 사용될 때는, 콜백 인터페이스 값의 연산을 호출하는 방식(이전 섹션 참조)과 유사하게 호출됩니다.

콜백 함수 타입 값 callable을 Web IDL 인자 리스트 args, 예외 동작 exceptionBehavior("report" 또는 "rethrow")와 선택적 콜백 this 값 thisArg로 콜백 함수 호출하기: 다음 단계를 수행합니다. 이 단계는 IDL 값을 반환하거나 예외를 throw합니다.

exceptionBehavior 인자는 callable의 반환 타입이 프라미스 타입이 아닐 때만 제공되어야 하며, callable의 반환 타입이 undefined 또는 any가 아니라면 반드시 "rethrow"여야 합니다.

콜 사이트가 이를 준수하도록 업데이트되기 전까지, 명세에서 해당 값을 제공하지 않으면 "rethrow"가 공급된 것으로 간주해야 합니다.
  1. completion을 초기화되지 않은 변수로 설정합니다.

  2. thisArg가 주어지지 않았다면 thisArg를 undefined로 설정합니다.

  3. F를 callable에 해당하는 자바스크립트 객체로 설정합니다.

  4. IsCallable(F)가 false이면:

    1. 참고: 이것은 콜백 함수가 [LegacyTreatNonObjectAsNull] 특성이 붙은 attribute에서 온 경우에만 발생할 수 있습니다.

    2. undefined를 콜백 함수의 반환 타입으로 변환한 결과를 반환합니다.

  5. realm을 F의 연결된 realm으로 설정합니다.

  6. relevant settings를 realm의 설정 객체로 설정합니다.

  7. stored settings를 callable의 콜백 컨텍스트로 설정합니다.

  8. 스크립트 실행 준비를 relevant settings로 실행합니다.

  9. 콜백 실행 준비를 stored settings로 실행합니다.

  10. jsArgs를 args를 자바스크립트 인자 리스트로 변환한 결과로 설정합니다. 변환 중 예외가 발생하면 completion을 예외를 나타내는 completion 값으로 설정하고 return 단계로 점프합니다.

  11. callResult를 Completion(Call(F, thisArg, jsArgs))로 설정합니다.

  12. callResult가 비정상 완료(abrupt completion)이면 completion을 callResult로 설정하고 return 단계로 점프합니다.

  13. completion을 callResult.[[Value]]를 callable의 반환 타입과 동일한 타입의 IDL 값으로 변환한 결과로 설정합니다. 변환 중 예외가 발생하면 completion을 예외를 나타내는 completion 값으로 설정합니다.

  14. Return: 이 시점에서 completion은 IDL 값이거나 비정상 완료입니다.

    1. 콜백 실행 후 정리(clean up)를 stored settings로 실행합니다.

    2. 스크립트 실행 후 정리(clean up)를 relevant settings로 실행합니다.

    3. completion이 IDL 값이면 completion을 반환합니다.

    4. 단언: completion은 비정상 완료이다.

    5. exceptionBehavior가 "rethrow"이면 completion.[[Value]]를 throw합니다.

    6. 그 외 exceptionBehavior가 "report"일 경우:

      1. 단언: callable의 반환 타입은 undefined 또는 any이다.

      2. 예외 보고를 completion.[[Value]]에 대해 realm의 글로벌 객체로 실행합니다.

      3. 유일한 undefined IDL 값을 반환합니다.

    7. 단언: callable의 반환 타입은 프라미스 타입이다.

    8. rejectedPromise를 ! Call(%Promise.reject%, %Promise%, «completion.[[Value]]»)로 설정합니다.

    9. rejectedPromise를 콜백 함수의 반환 타입으로 변환한 결과를 반환합니다.

일부 콜백 함수는 생성자(constructor)로 사용될 수 있습니다. 이런 콜백 함수는 프라미스 타입 반환 타입을 갖지 않아야 합니다.

콜백 함수 타입 값 callable을 Web IDL 인자 리스트 args로 콜백 함수 생성자 호출을 하려면 다음 단계를 수행합니다. 이 단계는 IDL 값을 반환하거나 예외를 throw합니다.

  1. completion을 초기화되지 않은 변수로 설정합니다.

  2. F를 callable에 해당하는 자바스크립트 객체로 설정합니다.

  3. IsConstructor(F)가 false이면 TypeError 예외를 throw합니다.

  4. realm을 F의 연결된 realm으로 설정합니다.

  5. relevant settings를 realm의 설정 객체로 설정합니다.

  6. stored settings를 callable의 콜백 컨텍스트로 설정합니다.

  7. 스크립트 실행 준비를 relevant settings로 실행합니다.

  8. 콜백 실행 준비를 stored settings로 실행합니다.

  9. jsArgs를 args를 자바스크립트 인자 리스트로 변환한 결과로 설정합니다. 변환 중 예외가 발생하면 completion을 예외를 나타내는 completion 값으로 설정하고 return 단계로 점프합니다.

  10. callResult를 Completion(Construct(F, jsArgs))로 설정합니다.

  11. callResult가 비정상 완료(abrupt completion)이면 completion을 callResult로 설정하고 return 단계로 점프합니다.

  12. completion을 callResult.[[Value]]를 callable의 반환 타입과 동일한 타입의 IDL 값으로 변환한 결과로 설정합니다. 변환 중 예외가 발생하면 completion을 예외를 나타내는 completion 값으로 설정합니다.

  13. Return: 이 시점에서 completion은 IDL 값이거나 비정상 완료입니다.

    1. 콜백 실행 후 정리(clean up)를 stored settings로 실행합니다.

    2. 스크립트 실행 후 정리(clean up)를 relevant settings로 실행합니다.

    3. completion이 비정상 완료이면 completion.[[Value]]를 throw합니다.

    4. completion을 반환합니다.

3.13. 네임스페이스

특정 네임스페이스가 특정 realm에 노출되는 경우, 해당 realm의 글로벌 객체에 대응하는 프로퍼티가 존재합니다. 프로퍼티 이름은 네임스페이스의 식별자이고, 값은 네임스페이스 객체라 부르는 객체입니다.

네임스페이스 객체의 특성은 § 3.13.1 네임스페이스 객체에서 설명합니다.

3.13.1. 네임스페이스 객체

특정 네임스페이스 namespace와 realm realm에 대해 네임스페이스 객체는 다음과 같이 생성됩니다:

  1. namespaceObject를 OrdinaryObjectCreate(realm.[[Intrinsics]].[[%Object.prototype%]])로 생성합니다.

  2. 정규 속성 정의 알고리즘을 namespace, namespaceObject, realm에 대해 실행합니다.

  3. 정규 연산 정의 알고리즘을 namespace, namespaceObject, realm에 대해 실행합니다.

  4. 상수 정의 알고리즘을 namespace, namespaceObject, realm에 대해 실행합니다.

  5. 각 노출된 인터페이스 interface 중, [LegacyNamespace] 확장 속성이 있고, 그 인자가 namespace의 식별자인 경우:

    1. id를 interface의 식별자로 설정합니다.

    2. interfaceObject를 인터페이스 객체 생성 알고리즘을 interface, id, realm에 대해 실행한 결과로 설정합니다.

    3. DefineMethodProperty(namespaceObject, id, interfaceObject, false)를 실행합니다.

  6. namespaceObject를 반환합니다.

네임스페이스 객체의 class string은 네임스페이스의 식별자입니다.

3.14. 예외

3.14.1. DOMException 커스텀 바인딩

JavaScript 바인딩에서, DOMException에 대한 인터페이스 프로토타입 객체는 그 [[Prototype]] 내부 슬롯이, 인터페이스 프로토타입 객체 생성 추상 연산에서 정의된 대로, 고유 객체 %Error.prototype%으로 설정된다. 또한 모든 내장 예외처럼 [[ErrorData]] 및 [[Stack]] 슬롯도 가진다.

추가로, 구현이 네이티브 Error 객체에 그 밖의 특별한 기능이나 비표준 속성(line 및 column 속성 등)을 제공한다면, 그것들도 DOMException 객체에 노출해야 한다.

3.14.2. 예외 객체

단순 예외는 해당 타입의 네이티브 자바스크립트 객체로 표현됩니다.

DOMException은 플랫폼 객체로 표현되며, DOMException 인터페이스를 구현합니다.

3.14.3. 예외 생성 및 throw

단순 예외 타입 T의 예외 생성 알고리즘:
  1. message를 예외 상황에 적합한 구현체 정의(implementation-defined) 메시지로 설정합니다. 호출 명세가 구현체가 메시지를 구성하는 데 참고할 수 있는 정보를 포함할 수 있습니다.

    구현체는 민감하거나 보안 정보가 누출되지 않도록 주의해야 합니다. 예를 들어 크로스 오리진 프레임의 URL, 사용자를 식별할 수 있는 정보 등이 포함되지 않아야 합니다.

  2. args를 « message »로 설정합니다.

  3. constructor를 현재 realm.[[Intrinsics]].[[%T%]]로 설정합니다.

  4. ! Construct(constructor, args)를 반환합니다.

DOMException의 예외 생성 알고리즘(name: name):
  1. 단언: name이 DOMException 이름 테이블에 포함되어 있다.

  2. ex를 new DOMException으로 현재 realm에서 생성합니다.

  3. ex의 name을 name으로 설정합니다.

  4. ex의 message를 예외 상황에 적합한 구현체 정의 메시지로 설정합니다. 호출 명세가 구현체가 메시지를 구성하는 데 참고할 수 있는 정보를 포함할 수 있습니다.

    구현체는 민감하거나 보안 정보가 누출되지 않도록 주의해야 합니다. 예를 들어 크로스 오리진 프레임의 URL, 사용자를 식별할 수 있는 정보 등이 포함되지 않아야 합니다.

  5. ex를 반환합니다.

DOMException 파생 인터페이스의 예외 생성 알고리즘(인터페이스 식별자 type, 추가 초기화 지침 포함):
  1. ex를 new type 인터페이스의 인스턴스로 현재 realm에서 생성합니다.

  2. ex의 name을 type으로 설정합니다.

  3. ex의 message를 예외 상황에 적합한 구현체 정의 메시지로 설정합니다. 호출 명세가 구현체가 메시지를 구성하는 데 참고할 수 있는 정보를 포함할 수 있습니다.

    구현체는 민감하거나 보안 정보가 누출되지 않도록 주의해야 합니다. 예를 들어 크로스 오리진 프레임의 URL, 사용자를 식별할 수 있는 정보 등이 포함되지 않아야 합니다.

  4. 호출자가 기술한 추가 초기화 작업을 ex에 대해 수행합니다.

  5. ex를 반환합니다.

예외 throw 알고리즘:
  1. O를 동일한 인자로 예외 생성 알고리즘을 실행한 결과로 설정합니다.

  2. O를 throw합니다.

위 알고리즘은 예외를 나타내는 객체가 함수 객체 밖으로 전파될 때, 그 realm과 연결된 것들로 제한한다. 이는 해당 함수 객체의 realm(즉, 함수가 실행되는 시점의 현재 realm)이다. 예를 들어, 다음 IDL을 생각해 보자:

[Exposed=Window]
interface MathUtils {
  // x가 음수면, "NotSupportedError" DOMException을 throw합니다.
  double computeSquareRoot(double x);
};

myMU가 다른 realm에서 온 MathUtils 객체라면, 메서드를 호출할 때 throw된 예외는 해당 메서드의 realm에서 생성된 예외가 됩니다:

const myMU = window.getMathUtils();          // 이 realm의 MathUtils 객체
const otherMU = otherWindow.getMathUtils();  // 다른 realm의 MathUtils 객체

myMU instanceof Object;                      // true
otherMU instanceof Object;                   // false
otherMU instanceof otherWindow.Object;       // true

try {
  otherMU.doComputation.call(myMU, -1);
} catch (e) {
  console.assert(!(e instanceof DOMException));
  console.assert(e instanceof otherWindow.DOMException);
}

3.14.4. 예외 처리

별도로 명시되지 않는 한, 본 문서의 요구사항에 따라 자바스크립트 런타임 의미론이 호출되고 예외가 throw되어 종료될 때, 해당 예외는 호출자에게 전파되어야 하며, 호출자에서 잡히지 않으면 그 상위 호출자에게 계속 전파되어야 합니다.

문서 규약에 따라, 본 문서에서 명세된 알고리즘은 throw된 예외를 가로채거나, 예외가 throw된 경우의 정확한 처리 단계를 명시하거나, 비정상 완료(abrupt completion)을 명시적으로 처리할 수 있습니다.

다음 IDL 조각(fragment)은 두 인터페이스와 하나의 예외를 정의합니다. ExceptionThrower의 valueOf 속성은 값을 얻으려 할 때마다 예외를 throw하도록 정의되어 있습니다.

[Exposed=Window]
interface Dahut {
  attribute DOMString type;
};

[Exposed=Window]
interface ExceptionThrower {
  // 이 속성은 항상 NotSupportedError를 throw하며 값을 반환하지 않습니다.
  attribute long valueOf;
};

이 인터페이스를 지원하는 자바스크립트 구현체가 있다고 가정할 때, 다음 코드는 예외가 어떻게 처리되는지 보여줍니다:

var d = getDahut();              // Dahut 인스턴스 얻기
var et = getExceptionThrower();  // ExceptionThrower 인스턴스 얻기

try {
  d.type = { toString: function() { throw "abc"; } };
} catch (e) {
  // 여기서 문자열 "abc"가 catch됩니다. 네이티브 객체를 문자열로 변환하는 과정에서
  // 익명 함수가 호출되고, [[DefaultValue]], ToPrimitive, ToString 알고리즘은
  // 예외 처리를 catch하지 않기 때문입니다.
}

try {
  d.type = { toString: { } };
} catch (e) {
  // 여기서 예외가 catch됩니다. 네이티브 객체의 toString 프로퍼티 값에 대해
  // [[Call]]을 시도하면서 발생합니다.
}

try {
  d.type = Symbol();
} catch (e) {
  // 여기서 예외가 catch됩니다. Symbol 값에 대해 자바스크립트 ToString 추상 연산을 시도하고 있기 때문입니다.
}

d.type = et;
// 여기서는 잡히지 않은 "NotSupportedError" DOMException이 throw됩니다.
// [[DefaultValue]] 알고리즘이 ExceptionThrower 객체의 "valueOf" 프로퍼티 값을 얻으려 시도하기 때문입니다.
// 이 예외는 이 코드 블록 밖으로 전파됩니다.

4. 공통 정의

이 절에서는 모든 적합 구현체가 지원해야 하는 몇 가지 공통 정의를 명세합니다.

4.1. ArrayBufferView

typedef (Int8Array or Int16Array or Int32Array or
         Uint8Array or Uint16Array or Uint32Array or Uint8ClampedArray or
         BigInt64Array or BigUint64Array or
         Float16Array or Float32Array or Float64Array or DataView) ArrayBufferView;

ArrayBufferView 타입은 ArrayBuffer나 SharedArrayBuffer ([AllowShared]이 사용될 때)에 대한 뷰를 제공하는 객체를 나타내는 데 사용됩니다.

4.2. BufferSource

typedef (ArrayBuffer or ArrayBufferView) BufferSource;

BufferSource 타입은 객체 자체가 ArrayBuffer이거나, ArrayBuffer에 대한 뷰를 제공하는 객체를 나타내는 데 사용됩니다.

참고: [AllowShared] 는 BufferSource와 함께 사용할 수 없습니다. ArrayBuffer가 이를 지원하지 않기 때문입니다. 대신 AllowSharedBufferSource를 사용하세요.

4.3. AllowSharedBufferSource

typedef (ArrayBuffer or SharedArrayBuffer or [AllowShared] ArrayBufferView) AllowSharedBufferSource;

AllowSharedBufferSource 타입은 객체 자체가 ArrayBuffer이거나 SharedArrayBuffer이거나, ArrayBuffer 또는 SharedArrayBuffer에 대한 뷰를 제공하는 객체를 나타내는 데 사용됩니다.

4.4. DOMException

DOMException 타입은 다음 IDL 조각으로 정의된 인터페이스 타입입니다:

[Exposed=*,
 Serializable]
interface DOMException { // but see below note about JavaScript binding
  constructor(optional DOMString message = "", optional DOMString name = "Error");
  readonly attribute DOMString name;
  readonly attribute DOMString message;
  readonly attribute unsigned short code;

  const unsigned short INDEX_SIZE_ERR = 1;
  const unsigned short DOMSTRING_SIZE_ERR = 2;
  const unsigned short HIERARCHY_REQUEST_ERR = 3;
  const unsigned short WRONG_DOCUMENT_ERR = 4;
  const unsigned short INVALID_CHARACTER_ERR = 5;
  const unsigned short NO_DATA_ALLOWED_ERR = 6;
  const unsigned short NO_MODIFICATION_ALLOWED_ERR = 7;
  const unsigned short NOT_FOUND_ERR = 8;
  const unsigned short NOT_SUPPORTED_ERR = 9;
  const unsigned short INUSE_ATTRIBUTE_ERR = 10;
  const unsigned short INVALID_STATE_ERR = 11;
  const unsigned short SYNTAX_ERR = 12;
  const unsigned short INVALID_MODIFICATION_ERR = 13;
  const unsigned short NAMESPACE_ERR = 14;
  const unsigned short INVALID_ACCESS_ERR = 15;
  const unsigned short VALIDATION_ERR = 16;
  const unsigned short TYPE_MISMATCH_ERR = 17;
  const unsigned short SECURITY_ERR = 18;
  const unsigned short NETWORK_ERR = 19;
  const unsigned short ABORT_ERR = 20;
  const unsigned short URL_MISMATCH_ERR = 21;
  const unsigned short QUOTA_EXCEEDED_ERR = 22;
  const unsigned short TIMEOUT_ERR = 23;
  const unsigned short INVALID_NODE_TYPE_ERR = 24;
  const unsigned short DATA_CLONE_ERR = 25;
};

참고: § 3.14.1 DOMException 사용자 정의 바인딩에서 논의한 것처럼, JavaScript 바인딩은 인터페이스 타입에 대한 일반 요구사항을 넘어서는 추가 요구사항을 부과한다.

각 DOMException 객체에는 연관된 name 및 message가 있으며, 둘 다 문자열이다.

new DOMException(message, name) 생성자 단계는 다음과 같다:

  1. this의 name을 name으로 설정한다.

  2. this의 message를 message로 설정한다.

name 게터 단계는 this의 name을 반환하는 것이다.

message 게터 단계는 this의 message를 반환하는 것이다.

code 게터 단계는 this의 name에 대해 DOMException 이름 표에 표시된 레거시 코드를 반환하거나, 그러한 항목이 표에 없으면 0을 반환하는 것이다.

DOMException 객체는 직렬화 가능 객체이다.

value 및 serialized가 주어졌을 때, 그 직렬화 단계는 다음과 같다:

  1. serialized.[[Name]]을 value의 name으로 설정한다.
  2. serialized.[[Message]]를 value의 message로 설정한다.
  3. serialized.[[Stack]]을 value.[[Stack]]에서 파생된 구현 정의 문자열로 설정한다.
  4. 사용자 에이전트는 아직 명시되지 않은 모든 관심 있는 부수 데이터, 특히 line 및 column 속성의 직렬화된 표현을 serialized에 첨부해야 한다.

value 및 serialized가 주어졌을 때, 그 역직렬화 단계는 다음과 같다:

  1. value의 name을 serialized.[[Name]]으로 설정한다.
  2. value의 message를 serialized.[[Message]]로 설정한다.
  3. value.[[Stack]]을 serialized.[[Stack]]으로 설정한다.
  4. 다른 데이터가 serialized에 첨부되어 있으면, 그것을 역직렬화하여 value에 첨부한다.

4.5. Function

callback Function = any (any... arguments);

Function 콜백 함수 타입은 인자에 어떤 제한도 없으며 반환값도 제한이 없는 함수 값을 나타내는 데 사용됩니다.

4.6. VoidFunction

callback VoidFunction = undefined ();

VoidFunction 콜백 함수 타입은 인자를 받지 않으며 반환값도 없는 함수 값을 나타내는 데 사용됩니다.

5. 확장성

이 절은 참고용입니다.

언어 바인딩 요구사항에 대한 확장은, 본 문서에서 정의된 것과 충돌하지 않는 확장 속성을 사용하여 명세할 수 있습니다. 개인이나 프로젝트별 사용을 위한 확장은 다른 명세에 나오는 IDL 조각에 포함하지 않아야 하며, 다른 명세에서 사용이 필요한 확장은 Web IDL 작업 그룹(작성 시점 기준 W3C Web Platform Working Group)과 협의하여 본 문서의 향후 버전에 포함될 수 있도록 하는 것이 좋습니다.

IDL 언어의 다른 측면에 대한 확장은 강력히 권장되지 않습니다.

6. 레거시 구성 요소

이 절은 참고용입니다.

레거시 Web IDL 구성 요소는 오직 레거시 웹 플랫폼 기능을 명세하기 위해 존재합니다. 일반적으로 "Legacy"라는 접두사가 붙습니다. 레거시 Web IDL 구성 요소는 레거시 웹 플랫폼 기능의 명세나 해당 기능과의 일관성을 위해 필요한 경우를 제외하면 명세에서 사용하는 것이 강력히 지양됩니다. 레거시 Web IDL 구성 요소 사용을 원하는 편집자는 진행 전에 이슈를 등록하여 논의하는 것이 좋습니다.

구성 요소를 레거시로 표시하는 것은 곧 본 문서에서 제거될 것임을 의미하지는 않습니다. 다만, 이것이 향후 본 문서에서 제거될 좋은 후보임을 시사하며, 여러 휴리스틱에 따라 해당 구성 요소가 명세하려는 웹 플랫폼 기능이 완전히 제거되거나 레거시 Web IDL 구성 요소를 사용하지 않고도 명세할 수 있게 되면 제거될 수 있음을 의미합니다.

7. 이 명세 참조

이 절은 참고용입니다.

여러 IDL 조각을 사용하여 웹 플랫폼 인터페이스를 정의하는 다른 명세들이 본 명세를 참조할 것으로 예상됩니다. 그런 명세들은 아래와 같은 문장을 포함하여, IDL이 본 명세에서 설명한 대로 해석되어야 함을 명시하는 것이 좋습니다:

이 명세의 부록 A에 있는 IDL 조각은, 본 명세의 규범적 참조에서 정의된 IDL 조각들과 함께, “Web IDL” 명세에서 설명한 대로 적합한 IDL 조각 집합에 대해 요구되는 대로 해석되어야 한다. [WEBIDL]

또한, 참조 명세에서 사용자 에이전트의 적합성 클래스는 본 명세의 적합 구현체 클래스로 연결하는 것이 좋습니다:

적합한 FooML 사용자 에이전트는 또한 본 명세의 부록 A의 IDL 조각에 대한 적합 구현체여야 하며, 이는 “Web IDL” 명세에서 설명한 대로 해석되어야 한다. [WEBIDL]

8. 프라이버시 및 보안 고려사항

이 명세는 자바스크립트와 IDL 값 사이의 변환 계층을 정의합니다. 이 계층을 잘못 구현하면 보안 문제가 발생할 수 있습니다.

이 명세는 또한 any 및 object IDL 타입을 통해 자바스크립트 값을 직접 사용할 수 있도록 합니다. 이러한 값들은 보안 문제를 피하기 위해 신중하게 다루어야 합니다. 특히, 사용자 스크립트는 이러한 값의 거의 모든 조작에 응답하여 실행될 수 있으며, 이를 사용하는 명세나 구현체의 기대치를 무효화할 수 있습니다.

이 명세는 SharedArrayBuffer 객체와의 상호작용도 가능하게 하는데, 이러한 객체는 타이밍 공격을 구축하는 데 사용할 수 있습니다. 이 객체를 사용하는 명세에서는 이러한 공격을 고려해야 합니다.

감사의 글

이 절은 참고용입니다.

편집자들은 다음 분들께 이 명세에 기여해 주신 것에 대해 감사의 말씀을 전합니다: Glenn Adams, David Andersson, Jake Archibald, Tab Atkins-Bittner, L. David Baron, Art Barstow, Nils Barth, Robin Berjon, David Bruant, Jan-Ivar Bruaroey, Marcos Cáceres, Giovanni Campagna, François Daoust, Domenic Denicola, Chris Dumez, Michael Dyck, Daniel Ehrenberg, Brendan Eich, João Eiras, Gorm Haug Eriksen, Sigbjorn Finne, David Flanagan, Aryeh Gregor, Dimitry Golubovsky, James Graham, Aryeh Gregor, Tiancheng “Timothy” Gu, Kartikaya Gupta, Marcin Hanclik, Jed Hartman, Stefan Haustein, Dominique Hazaël-Massieux, Ian Hickson, Björn Höhrmann, Kyle Huey, Lachlan Hunt, Oliver Hunt, Jim Jewett, Wolfgang Keller, Anne van Kesteren, Olav Junker Kjær, Takayoshi Kochi, Magnus Kristiansen, Raphael Kubo da Costa, Takeshi Kurosawa, Yves Lafon, Travis Leithead, Jim Ley, Kevin Lindsey, Jens Lindström, Peter Linss, 呂康豪 (Kang-Hao Lu), Kyle Machulis, Darien Maillet Valentine, Mark Miller, Ms2ger, Andrew Oakley, 岡坂 史紀 (Shiki Okasaka), Jason Orendorff, Olli Pettay, Simon Pieters, Andrei Popescu, François Remy, Tim Renouf, Jeremy Roman, Tim Ruffles, Alex Russell, Takashi Sakamoto, Doug Schepers, Jonas Sicking, Garrett Smith, Sam Sneddon, Jungkee Song, Josh Soref, Maciej Stachowiak, Austin Sullivan, Anton Tayanovskyy, triple-underscore, Peter Van der Beken, Jeff Walden, Allen Wirfs-Brock, Jeffrey Yasskin 그리고, Collin Xu.

편집자가 명세 관리를 할 수 없었던 기간 동안 이 문서를 관리해 준 Sam Weinig에게도 특별히 감사를 전합니다.

이 현행 표준은 Edgar Chen (Mozilla, echen@mozilla.com)과 Tiancheng "Timothy" Gu (timothygu99@gmail.com)가 집필하였으며, Boris Zbarsky (bzbarsky@mit.edu), Cameron McCormack (cam@mcc.id.au), 그리고 Tobie Langel (tobie@unlockopen.com)의 중요한 기여가 있었습니다.

IDL 문법

이 절에서는 시작 기호 Definitions가 전체 IDL 조각과 매칭되는 LL(1) 문법을 정의합니다.

문법의 각 생성식(production)은 오른쪽에 0이 아닌 개수의 터미널과 비터미널 기호가 있거나, 기호가 없음을 나타내는 엡실론(ε)이 있습니다. 대문자로 시작하는 기호는 비터미널 기호입니다. 고정폭 글꼴로 표시되는 기호는 터미널 기호입니다. 소문자로 시작하는 산세리프 글꼴의 기호는 터미널 기호로, 다음과 같이 Perl 5 정규표현식 문법([PERLRE])을 사용해 매칭됩니다:

integer = /-?([1-9][0-9]*|0[Xx][0-9A-Fa-f]+|0[0-7]*)/
decimal = /-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)/
identifier = /[_-]?[A-Za-z][0-9A-Z_a-z-]*/
string = /"[^"]*"/
whitespace = /[\t\n\r ]+/
comment = /\/\/.*|\/\*(.|\n)*?\*\//
other = /[^\t\n\r 0-9A-Za-z]/

토크나이저는 스칼라 값 시퀀스에 대해 동작합니다. 토크나이징할 때는 가능한 가장 긴 일치 항목을 사용해야 합니다. 예를 들어, 입력 텍스트가 “a1”이면 하나의 identifier로 토크나이즈되고, identifier와 integer로 분리되지 않습니다. 가장 긴 일치가 위에 명시된 터미널 심볼 또는 문법의 다른 터미널 심볼 중 하나와 모두 일치할 수 있으면, 후자가 되도록 토크나이즈해야 합니다. 따라서 입력 텍스트 “long”은 터미널 심볼 long으로 토크나이즈되고, identifier "long"이 아닙니다. “.”는 터미널 심볼 .로 토크나이즈되며, other가 아닙니다.

IDL 문법은 고정폭 터미널 심볼과 identifier 터미널의 값 모두에 대해 대소문자를 구분합니다. 예를 들어, 입력 텍스트 “Const”는 identifier로 토크나이즈되고 터미널 심볼 const가 아닙니다. interface의 identifier가 "A"인 것과 "a"인 것은 구분됩니다. 또한 확장 속성 [legacyfactoryfunction]은 [LegacyFactoryFunction] 확장 속성으로 인식되지 않습니다.

암시적으로, 파싱되는 입력 텍스트의 모든 터미널 사이에는 임의 개수의 whitespace 및 comment 터미널이 허용됩니다. 이러한 whitespace와 comment 터미널은 파싱 중에 무시됩니다.

아래의 LL(1) 문법은 Definitions에서 시작하여 IDL 조각에 매칭됩니다:

Definitions ::
    ExtendedAttributeList Definition Definitions
    ε

Definition ::
    CallbackOrInterfaceOrMixin
    Namespace
    Partial
    Dictionary
    Enum
    Typedef
    IncludesStatement

ArgumentNameKeyword ::
    attribute
    callback
    const
    constructor
    deleter
    dictionary
    enum
    getter
    includes
    inherit
    interface
    iterable
    maplike
    mixin
    namespace
    partial
    readonly
    required
    setlike
    setter
    static
    stringifier
    typedef
    unrestricted

CallbackOrInterfaceOrMixin ::
    callback CallbackRestOrInterface
    interface InterfaceOrMixin

InterfaceOrMixin ::
    InterfaceRest
    MixinRest

InterfaceRest ::
    identifier Inheritance { InterfaceMembers } ;

Partial ::
    partial PartialDefinition

PartialDefinition ::
    interface PartialInterfaceOrPartialMixin
    PartialDictionary
    Namespace

PartialInterfaceOrPartialMixin ::
    PartialInterfaceRest
    MixinRest

PartialInterfaceRest ::
    identifier { PartialInterfaceMembers } ;

InterfaceMembers ::
    ExtendedAttributeList InterfaceMember InterfaceMembers
    ε

InterfaceMember ::
    PartialInterfaceMember
    Constructor

PartialInterfaceMembers ::
    ExtendedAttributeList PartialInterfaceMember PartialInterfaceMembers
    ε

PartialInterfaceMember ::
    Const
    Operation
    Stringifier
    StaticMember
    Iterable
    AsyncIterable
    ReadOnlyMember
    ReadWriteAttribute
    ReadWriteMaplike
    ReadWriteSetlike
    InheritAttribute

Inheritance ::
    : identifier
    ε

MixinRest ::
    mixin identifier { MixinMembers } ;

MixinMembers ::
    ExtendedAttributeList MixinMember MixinMembers
    ε

MixinMember ::
    Const
    RegularOperation
    Stringifier
    OptionalReadOnly AttributeRest

IncludesStatement ::
    identifier includes identifier ;

CallbackRestOrInterface ::
    CallbackRest
    interface identifier { CallbackInterfaceMembers } ;

CallbackInterfaceMembers ::
    ExtendedAttributeList CallbackInterfaceMember CallbackInterfaceMembers
    ε

CallbackInterfaceMember ::
    Const
    RegularOperation

Const ::
    const ConstType identifier = ConstValue ;

ConstValue ::
    BooleanLiteral
    FloatLiteral
    integer

BooleanLiteral ::
    true
    false

FloatLiteral ::
    decimal
    -Infinity
    Infinity
    NaN

ConstType ::
    PrimitiveType
    identifier

ReadOnlyMember ::
    readonly ReadOnlyMemberRest

ReadOnlyMemberRest ::
    AttributeRest
    MaplikeRest
    SetlikeRest

ReadWriteAttribute ::
    AttributeRest

InheritAttribute ::
    inherit AttributeRest

AttributeRest ::
    attribute TypeWithExtendedAttributes AttributeName ;

AttributeName ::
    AttributeNameKeyword
    identifier

AttributeNameKeyword ::
    required

OptionalReadOnly ::
    readonly
    ε

DefaultValue ::
    ConstValue
    string
    [ ]
    { }
    null
    undefined

Operation ::
    RegularOperation
    SpecialOperation

RegularOperation ::
    Type OperationRest

SpecialOperation ::
    Special RegularOperation

Special ::
    getter
    setter
    deleter

OperationRest ::
    OptionalOperationName ( ArgumentList ) ;

OptionalOperationName ::
    OperationName
    ε

OperationName ::
    OperationNameKeyword
    identifier

OperationNameKeyword ::
    includes

ArgumentList ::
    Argument Arguments
    ε

Arguments ::
    , Argument Arguments
    ε

Argument ::
    ExtendedAttributeList ArgumentRest

ArgumentRest ::
    optional TypeWithExtendedAttributes ArgumentName Default
    Type Ellipsis ArgumentName

ArgumentName ::
    ArgumentNameKeyword
    identifier

Ellipsis ::
    ...
    ε

Constructor ::
    constructor ( ArgumentList ) ;

Stringifier ::
    stringifier StringifierRest

StringifierRest ::
    OptionalReadOnly AttributeRest
    ;

StaticMember ::
    static StaticMemberRest

StaticMemberRest ::
    OptionalReadOnly AttributeRest
    RegularOperation

Iterable ::
    iterable < TypeWithExtendedAttributes OptionalType > ;

OptionalType ::
    , TypeWithExtendedAttributes
    ε

AsyncIterable ::
    async_iterable < TypeWithExtendedAttributes OptionalType > OptionalArgumentList ;

OptionalArgumentList ::
    ( ArgumentList )
    ε

ReadWriteMaplike ::
    MaplikeRest

MaplikeRest ::
    maplike < TypeWithExtendedAttributes , TypeWithExtendedAttributes > ;

ReadWriteSetlike ::
    SetlikeRest

SetlikeRest ::
    setlike < TypeWithExtendedAttributes > ;

Namespace ::
    namespace identifier { NamespaceMembers } ;

NamespaceMembers ::
    ExtendedAttributeList NamespaceMember NamespaceMembers
    ε

NamespaceMember ::
    RegularOperation
    readonly AttributeRest
    Const

Dictionary ::
    dictionary identifier Inheritance { DictionaryMembers } ;

DictionaryMembers ::
    DictionaryMember DictionaryMembers
    ε

DictionaryMember ::
    ExtendedAttributeList DictionaryMemberRest

DictionaryMemberRest ::
    required TypeWithExtendedAttributes identifier ;
    Type identifier Default ;

PartialDictionary ::
    dictionary identifier { DictionaryMembers } ;

Default ::
    = DefaultValue
    ε

Enum ::
    enum identifier { EnumValueList } ;

EnumValueList ::
    string EnumValueListComma

EnumValueListComma ::
    , EnumValueListString
    ε

EnumValueListString ::
    string EnumValueListComma
    ε

CallbackRest ::
    identifier = Type ( ArgumentList ) ;

Typedef ::
    typedef TypeWithExtendedAttributes identifier ;

Type ::
    SingleType
    UnionType Null

TypeWithExtendedAttributes ::
    ExtendedAttributeList Type

SingleType ::
    DistinguishableType
    any
    PromiseType

UnionType ::
    ( UnionMemberType or UnionMemberType UnionMemberTypes )

UnionMemberType ::
    ExtendedAttributeList DistinguishableType
    UnionType Null

UnionMemberTypes ::
    or UnionMemberType UnionMemberTypes
    ε

DistinguishableType ::
    PrimitiveType Null
    StringType Null
    identifier Null
    sequence < TypeWithExtendedAttributes > Null
    async_sequence < TypeWithExtendedAttributes > Null
    object Null
    symbol Null
    BufferRelatedType Null
    FrozenArray < TypeWithExtendedAttributes > Null
    ObservableArray < TypeWithExtendedAttributes > Null
    RecordType Null
    undefined Null

PrimitiveType ::
    UnsignedIntegerType
    UnrestrictedFloatType
    boolean
    byte
    octet
    bigint

UnrestrictedFloatType ::
    unrestricted FloatType
    FloatType

FloatType ::
    float
    double

UnsignedIntegerType ::
    unsigned IntegerType
    IntegerType

IntegerType ::
    short
    long OptionalLong

OptionalLong ::
    long
    ε

StringType ::
    ByteString
    DOMString
    USVString

PromiseType ::
    Promise < Type >

RecordType ::
    record < StringType , TypeWithExtendedAttributes >

Null ::
    ?
    ε

BufferRelatedType ::
    ArrayBuffer
    SharedArrayBuffer
    DataView
    Int8Array
    Int16Array
    Int32Array
    Uint8Array
    Uint16Array
    Uint32Array
    Uint8ClampedArray
    BigInt64Array
    BigUint64Array
    Float16Array
    Float32Array
    Float64Array

ExtendedAttributeList ::
    [ ExtendedAttribute ExtendedAttributes ]
    ε

ExtendedAttributes ::
    , ExtendedAttribute ExtendedAttributes
    ε

ExtendedAttribute ::
    ( ExtendedAttributeInner ) ExtendedAttributeRest
    [ ExtendedAttributeInner ] ExtendedAttributeRest
    { ExtendedAttributeInner } ExtendedAttributeRest
    Other ExtendedAttributeRest

ExtendedAttributeRest ::
    ExtendedAttribute
    ε

ExtendedAttributeInner ::
    ( ExtendedAttributeInner ) ExtendedAttributeInner
    [ ExtendedAttributeInner ] ExtendedAttributeInner
    { ExtendedAttributeInner } ExtendedAttributeInner
    OtherOrComma ExtendedAttributeInner
    ε

Other ::
    integer
    decimal
    identifier
    string
    other
    -
    -Infinity
    .
    ...
    :
    ;
    <
    =
    >
    ?
    *
    ByteString
    DOMString
    FrozenArray
    Infinity
    NaN
    ObservableArray
    Promise
    USVString
    any
    bigint
    boolean
    byte
    double
    false
    float
    long
    null
    object
    octet
    or
    optional
    record
    sequence
    short
    symbol
    true
    unsigned
    undefined
    ArgumentNameKeyword
    BufferRelatedType

OtherOrComma ::
    Other
    ,

IdentifierList ::
    identifier Identifiers

Identifiers ::
    , identifier Identifiers
    ε

IntegerList ::
    integer Integers

Integers ::
    , integer Integers
    ε

ExtendedAttributeNoArgs ::
    identifier

ExtendedAttributeArgList ::
    identifier ( ArgumentList )

ExtendedAttributeIdent ::
    identifier = identifier

ExtendedAttributeString ::
    identifier = string

ExtendedAttributeInteger ::
    identifier = integer

ExtendedAttributeDecimal ::
    identifier = decimal

ExtendedAttributeWildcard ::
    identifier = *

ExtendedAttributeIdentList ::
    identifier = ( IdentifierList )

ExtendedAttributeIntegerList ::
    identifier = ( IntegerList )

ExtendedAttributeNamedArgList ::
    identifier = identifier ( ArgumentList )

참고: Other 비단말은 (, ), [, ], {, } 그리고 ,를 제외한 모든 단일 단말 기호와 일치합니다.

ExtendedAttribute 비단말은 괄호, 대괄호, 중괄호가 균형을 이루고 , 토큰이 그 균형 잡힌 괄호 안에서만 나타나는 한, 비어 있지 않은 단말 기호 시퀀스와 일치하지만, 이러한 가능한 시퀀스 중 오직 일부만이 이 명세에서 정의된 확장 속성 에서 사용됩니다 — 사용되는 확장 속성의 구문에 대해서는 § 2.14 확장 속성 을 참조하세요.

문서 관례

이 문서에서는 다음과 같은 서체 관례를 사용합니다:

이 문서의 알고리즘에서는 다음과 같은 관례를 사용합니다:

적합성

이 명세서의 모든 내용은 도표, 예시, 참고 및 정보용으로 표시된 섹션을 제외하면 규범적입니다.

이 명세서는 Infra 표준에 의존합니다. [INFRA]

이 명세서에서는 다음과 같은 적합성 클래스가 정의됩니다:

적합한 IDL 조각 집합

IDL 조각들의 집합은, 함께 고려했을 때, 이 명세서에서 IDL 조각에 적용되는 must-, required-, shall- 수준의 기준을 모두 충족시키면 적합한 IDL 조각 집합으로 간주됩니다.

적합한 구현

사용자 에이전트가 지원하는 모든 언어 바인딩에 대해 구현에 적용되는 must-, required-, shall- 수준의 기준을 이 명세서에서 모두 충족시키면, 해당 사용자 에이전트는 적합한 구현으로, 해당 적합한 IDL 조각 집합에 대해 간주됩니다.

적합한 JavaScript 구현

사용자 에이전트가 JavaScript 언어 바인딩에 대해 구현에 적용되는 must-, required-, shall- 수준의 기준을 이 명세서에서 모두 충족시키면, 해당 사용자 에이전트는 적합한 JavaScript 구현으로, 해당 적합한 IDL 조각 집합에 대해 간주됩니다.

지적 재산권

이 현행 표준에는 W3C의 WebIDL [sic] Level 1에서 복사된 자료가 포함되어 있으며, 해당 자료는 W3C 소프트웨어 및 문서 라이선스에 따라 제공됩니다.

Copyright © WHATWG (Apple, Google, Mozilla, Microsoft). 이 저작물은 크리에이티브 커먼즈 저작자 표시 4.0 국제 라이선스에 따라 라이선스가 부여됩니다. 일부 내용이 소스 코드에 통합된 범위 내에서는, 해당 소스 코드의 부분은 BSD 3-Clause 라이선스에 따라 별도로 라이선스됩니다.

이것이 현행 표준입니다. 특허 검토용 버전에 관심이 있는 분은 현행 표준 검토 초안을 참고하시기 바랍니다.

색인

이 명세에서 정의된 용어

참조로 정의된 용어

참고 문헌

규범적 참고 문헌

[DOM]
Anne van Kesteren. DOM 표준. 현행 표준. URL: https://dom.spec.whatwg.org/
[ECMA-262]
ECMAScript 언어 명세. URL: https://tc39.es/ecma262/multipage/
[ECMA-402]
ECMAScript 국제화 API 명세. URL: https://tc39.es/ecma402/
[HTML]
Anne van Kesteren; et al. HTML 표준. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[IEEE-754]
IEEE 부동소수점 산술 표준. 2019년 7월 22일. URL: https://ieeexplore.ieee.org/document/8766229
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준. 현행 표준. URL: https://infra.spec.whatwg.org/
[PERLRE]
Perl 정규식 (Perl 5.8.8). 2006년 2월. URL: http://search.cpan.org/dist/perl/pod/perlre.pod
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. 현행 표준. URL: https://webidl.spec.whatwg.org/

정보용 참고 문헌

[API-DESIGN-PRINCIPLES]
Jeffrey Yasskin. 웹 플랫폼 설계 원칙. URL: https://w3ctag.github.io/design-principles/
[CSS3-CONDITIONAL]
Chris Lilley; David Baron; Elika Etemad. CSS 조건부 규칙 모듈 3단계. URL: https://drafts.csswg.org/css-conditional-3/
[CSSOM]
Daniel Glazman; Emilio Cobos Álvarez. CSS 오브젝트 모델 (CSSOM). URL: https://drafts.csswg.org/cssom/
[FETCH]
Anne van Kesteren. Fetch 표준. 현행 표준. URL: https://fetch.spec.whatwg.org/
[INDEXEDDB]
Nikunj Mehta; et al. Indexed Database API. URL: https://w3c.github.io/IndexedDB/
[PROPOSAL-FLOAT16ARRAY]
JavaScript에 float16 TypedArrays 추가 제안. URL: https://tc39.es/proposal-float16array/
[SERVICE-WORKERS]
Monica CHINTALA; Yoshisato Yanagisawa. Service Workers Nightly. URL: https://w3c.github.io/ServiceWorker/
[STREAMS]
Adam Rice; et al. Streams 표준. 현행 표준. URL: https://streams.spec.whatwg.org/
[WASM-JS-API-1]
Daniel Ehrenberg. WebAssembly JavaScript 인터페이스. URL: https://webassembly.github.io/spec/js-api/
[WASM-JS-API-2]
. Ms2ger; Ryan Hunt. WebAssembly JavaScript 인터페이스. URL: https://webassembly.github.io/spec/js-api/
[XML-NAMES]
Tim Bray; et al. Namespaces in XML 1.0 (세 번째 판). 2009년 12월 8일. REC. URL: https://www.w3.org/TR/xml-names/

IDL 색인

[Exposed=*, Serializable]
interface QuotaExceededError : DOMException {
  constructor(optional DOMString message = "", optional QuotaExceededErrorOptions options = {});

  readonly attribute double? quota;
  readonly attribute double? requested;
};

dictionary QuotaExceededErrorOptions {
  double quota;
  double requested;
};

typedef (Int8Array or Int16Array or Int32Array or
         Uint8Array or Uint16Array or Uint32Array or Uint8ClampedArray or
         BigInt64Array or BigUint64Array or
         Float16Array or Float32Array or Float64Array or DataView) ArrayBufferView;

typedef (ArrayBuffer or ArrayBufferView) BufferSource;
typedef (ArrayBuffer or SharedArrayBuffer or [AllowShared] ArrayBufferView) AllowSharedBufferSource;
[Exposed=*,
 Serializable]
interface DOMException { // but see below note about JavaScript binding
  constructor(optional DOMString message = "", optional DOMString name = "Error");
  readonly attribute DOMString name;
  readonly attribute DOMString message;
  readonly attribute unsigned short code;

  const unsigned short INDEX_SIZE_ERR = 1;
  const unsigned short DOMSTRING_SIZE_ERR = 2;
  const unsigned short HIERARCHY_REQUEST_ERR = 3;
  const unsigned short WRONG_DOCUMENT_ERR = 4;
  const unsigned short INVALID_CHARACTER_ERR = 5;
  const unsigned short NO_DATA_ALLOWED_ERR = 6;
  const unsigned short NO_MODIFICATION_ALLOWED_ERR = 7;
  const unsigned short NOT_FOUND_ERR = 8;
  const unsigned short NOT_SUPPORTED_ERR = 9;
  const unsigned short INUSE_ATTRIBUTE_ERR = 10;
  const unsigned short INVALID_STATE_ERR = 11;
  const unsigned short SYNTAX_ERR = 12;
  const unsigned short INVALID_MODIFICATION_ERR = 13;
  const unsigned short NAMESPACE_ERR = 14;
  const unsigned short INVALID_ACCESS_ERR = 15;
  const unsigned short VALIDATION_ERR = 16;
  const unsigned short TYPE_MISMATCH_ERR = 17;
  const unsigned short SECURITY_ERR = 18;
  const unsigned short NETWORK_ERR = 19;
  const unsigned short ABORT_ERR = 20;
  const unsigned short URL_MISMATCH_ERR = 21;
  const unsigned short QUOTA_EXCEEDED_ERR = 22;
  const unsigned short TIMEOUT_ERR = 23;
  const unsigned short INVALID_NODE_TYPE_ERR = 24;
  const unsigned short DATA_CLONE_ERR = 25;
};

callback Function = any (any... arguments);
callback VoidFunction = undefined ();
✔MDN
✔MDN
✔MDN
✔MDN