페이지 표시 설정

9 실행 가능 코드와 실행 컨텍스트

9.1 Environment Record

Environment Record는 ECMAScript 코드의 렉시컬 중첩 구조를 기반으로 Identifier를 특정 변수 및 함수와 연결하는 관계를 정의하는 데 사용하는 명세 타입입니다. 일반적으로 Environment Record는 FunctionDeclaration, BlockStatement 또는 TryStatement의 Catch 절과 같은 ECMAScript 코드의 특정 구문 구조와 연결됩니다. 이러한 코드가 평가될 때마다 해당 코드가 생성하는 식별자 바인딩을 기록하기 위해 새로운 Environment Record가 생성됩니다.

모든 Environment Record에는 [[OuterEnv]] 필드가 있으며, 이 필드는 null이거나 바깥쪽 Environment Record에 대한 참조입니다. 이는 Environment Record의 논리적 중첩을 모델링하는 데 사용됩니다. (안쪽) Environment Record의 바깥쪽 참조는 해당 안쪽 Environment Record를 논리적으로 둘러싸는 Environment Record에 대한 참조입니다. 물론 바깥쪽 Environment Record 자체도 자신의 바깥쪽 Environment Record를 가질 수 있습니다. 하나의 Environment Record는 여러 안쪽 Environment Record의 바깥쪽 환경으로 사용될 수 있습니다. 예를 들어 FunctionDeclaration에 두 개의 중첩된 FunctionDeclaration이 포함되어 있으면, 각 중첩 함수의 Environment Record는 둘러싸는 함수의 현재 평가에 대한 Environment Record를 바깥쪽 Environment Record로 갖습니다.

Environment Record는 순수하게 명세상의 메커니즘이며 ECMAScript 구현체의 특정 산출물과 대응할 필요는 없습니다. ECMAScript 프로그램에서 이러한 값에 직접 접근하거나 조작하는 것은 불가능합니다.

9.1.1 Environment Record 타입 계층

Environment Record는 단순한 객체 지향 계층 구조에 존재한다고 생각할 수 있습니다. 여기에서 Environment Record는 세 개의 구체적인 하위 클래스인 Declarative Environment Record, Object Environment Record 및 Global Environment Record를 갖는 추상 클래스입니다. Function Environment Record와 Module Environment Record는 Declarative Environment Record의 하위 클래스입니다.

Environment Record 추상 클래스에는 표 15에 정의된 추상 명세 메서드가 포함됩니다. 이러한 추상 메서드는 각 구체적인 하위 클래스마다 서로 다른 구체적 알고리즘을 갖습니다.

표 15: Environment Records의 추상 메서드
메서드 목적 정의
HasBinding ( name )

추상 메서드 HasBinding. 인수 name (String). 반환값: (정상 완료 (값: Boolean) 또는 throw 완료).

Environment Record에 name에 대한 바인딩이 있는지 결정합니다.
다음 타입에 구체적인 정의가 있습니다:
CreateMutableBinding ( name, deletable )

추상 메서드 CreateMutableBinding. 인수 name (String) 및 deletable (Boolean). 반환값: (정상 완료 (값: unused) 또는 throw 완료).

Environment Record에 새롭지만 초기화되지 않은 변경 가능한 바인딩을 생성합니다. name은 바인딩된 이름의 텍스트입니다. deletable이 true이면 나중에 해당 바인딩을 삭제할 수 있습니다.
다음 타입에 구체적인 정의가 있습니다:
CreateImmutableBinding ( name, strict )

추상 메서드 CreateImmutableBinding. 인수 name (String) 및 strict (Boolean). 반환값: (정상 완료 (값: unused) 또는 throw 완료).

Environment Record에 새롭지만 초기화되지 않은 변경 불가능한 바인딩을 생성합니다. name은 바인딩된 이름의 텍스트입니다. strict가 true이면 해당 바인딩이 초기화된 후 이를 설정하려는 시도는 해당 바인딩을 참조하는 연산의 엄격 모드 설정과 관계없이 항상 예외를 던집니다.
다음 타입에 구체적인 정의가 있습니다:
InitializeBinding ( name, value )

추상 메서드 InitializeBinding. 인수 name (String) 및 value (ECMAScript 언어 값). 반환값: (정상 완료 (값: unused) 또는 throw 완료).

Environment Record에 이미 존재하지만 초기화되지 않은 바인딩의 값을 설정합니다. name은 바인딩된 이름의 텍스트입니다. value는 바인딩에 사용할 값입니다.
다음 타입에 구체적인 정의가 있습니다:
SetMutableBinding ( name, value, strict )

추상 메서드 SetMutableBinding. 인수 name (String), value (ECMAScript 언어 값) 및 strict (Boolean). 반환값: (정상 완료 (값: unused) 또는 throw 완료).

Environment Record에 이미 존재하는 변경 가능한 바인딩의 값을 설정합니다. name은 바인딩된 이름의 텍스트입니다. value는 바인딩의 값입니다. strict가 true이고 바인딩을 설정할 수 없으면 TypeError 예외를 던집니다.
다음 타입에 구체적인 정의가 있습니다:
GetBindingValue ( name, strict )

추상 메서드 GetBindingValue. 인수 name (String) 및 strict (Boolean). 반환값: (정상 완료 (값: ECMAScript 언어 값) 또는 throw 완료).

Environment Record에 이미 존재하는 바인딩의 값을 반환합니다. name은 바인딩된 이름의 텍스트입니다. strict는 엄격 모드 코드에서 시작된 참조 또는 그 밖에 엄격 모드 참조 의미론이 필요한 참조를 식별하는 데 사용됩니다. strict가 true이고 바인딩이 존재하지 않으면 ReferenceError 예외를 던집니다. 바인딩은 존재하지만 초기화되지 않았으면 strict 값과 관계없이 ReferenceError를 던집니다.
다음 타입에 구체적인 정의가 있습니다:
DeleteBinding ( name )

추상 메서드 DeleteBinding. 인수 name (String). 반환값: (정상 완료 (값: Boolean) 또는 throw 완료).

Environment Record에서 바인딩을 삭제합니다. name은 바인딩된 이름의 텍스트입니다. name에 대한 바인딩이 존재하면 해당 바인딩을 제거하고 true를 반환합니다. 바인딩이 존재하지만 제거할 수 없으면 false를 반환합니다. 바인딩이 존재하지 않으면 true를 반환합니다.
다음 타입에 구체적인 정의가 있습니다:
HasThisBinding ( )

추상 메서드 HasThisBinding. 인수 없음. 반환값: Boolean.

Environment Record가 this 바인딩을 설정하는지 결정합니다. 설정하면 true를 반환하고 그렇지 않으면 false를 반환합니다.
다음 타입에 구체적인 정의가 있습니다:
GetThisBinding ( )

추상 메서드 GetThisBinding. 인수 없음. 반환값: (정상 완료 (값: ECMAScript 언어 값) 또는 throw 완료).

이 Environment Record의 this 바인딩 값을 반환합니다. this 바인딩이 초기화되지 않았으면 ReferenceError를 던집니다.
다음 타입에 구체적인 정의가 있습니다:
HasSuperBinding ( )

추상 메서드 HasSuperBinding. 인수 없음. 반환값: Boolean.

Environment Record가 super 메서드 바인딩을 설정하는지 결정합니다. 설정하면 true를 반환하고 그렇지 않으면 false를 반환합니다. true를 반환하면 해당 Environment Record가 Function Environment Record임을 의미하지만, 그 역은 성립하지 않습니다.
다음 타입에 구체적인 정의가 있습니다:
WithBaseObject ( )

추상 메서드 WithBaseObject. 인수 없음. 반환값: (Object 또는 undefined).

이 Environment Record가 with 문과 연결되어 있으면 with 객체를 반환합니다. 그렇지 않으면 undefined를 반환합니다.
다음 타입에 구체적인 정의가 있습니다:

9.1.1.1 Declarative Environment Record

각 Declarative Environment Record는 변수, 상수, let, 클래스, 모듈, import 및/또는 함수 선언을 포함하는 ECMAScript 프로그램 스코프와 연결됩니다. Declarative Environment Record는 해당 스코프 안의 선언에서 정의한 식별자 집합을 바인딩합니다.

모든 Declarative Environment Record에는 DisposableResource Record의 List를 포함하는 [[DisposableResourceStack]] 필드도 있습니다. 이 목록의 요소는 Environment Record를 생성한 Evaluation 단계가 완료될 때 폐기해야 하는 using 선언 및 await using 선언에 의해 추적됩니다.

9.1.1.1.1 HasBinding ( name )

a Declarative Environment Record envRecord의 구체 메서드 HasBinding. 인수 name (String). 반환값: 정상 완료 (값: Boolean). 인수 식별자가 해당 Record에 의해 바인딩된 식별자 중 하나인지 결정합니다. 호출되면 다음 단계를 수행한다.

  1. envRecord에 name에 대한 바인딩이 있으면, true를 반환합니다.
  2. false를 반환합니다.

9.1.1.1.2 CreateMutableBinding ( name, deletable )

a Declarative Environment Record envRecord의 구체 메서드 CreateMutableBinding. 인수 name (String) 및 deletable (Boolean). 반환값: 정상 완료 (값: unused). 초기화되지 않은 이름 name에 대한 새로운 변경 가능한 바인딩을 생성합니다. 이 Environment Record에는 name에 대한 바인딩이 이미 존재해서는 안 됩니다. deletable이 true이면 새 바인딩을 삭제할 수 있는 것으로 표시합니다. 호출되면 다음 단계를 수행한다.

  1. 단언: envRecord에는 name에 대한 바인딩이 이미 존재하지 않습니다.
  2. envRecord에 name에 대한 변경 가능한 바인딩을 생성하고 초기화되지 않았음을 기록합니다. deletable이 true이면 새로 생성한 바인딩을 이후의 DeleteBinding 호출로 삭제할 수 있음을 기록합니다.
  3. unused를 반환합니다.

9.1.1.1.3 CreateImmutableBinding ( name, strict )

a Declarative Environment Record envRecord의 구체 메서드 CreateImmutableBinding. 인수 name (String) 및 strict (Boolean). 반환값: 정상 완료 (값: unused). 초기화되지 않은 이름 name에 대한 새로운 변경 불가능한 바인딩을 생성합니다. 이 Environment Record에는 name에 대한 바인딩이 이미 존재해서는 안 됩니다. strict가 true이면 새 바인딩을 엄격 바인딩으로 표시합니다. 호출되면 다음 단계를 수행한다.

  1. 단언: envRecord에는 name에 대한 바인딩이 이미 존재하지 않습니다.
  2. envRecord에 name에 대한 변경 불가능한 바인딩을 생성하고 초기화되지 않았음을 기록합니다. strict가 true이면 새로 생성한 바인딩을 엄격 바인딩으로 기록합니다.
  3. unused를 반환합니다.

9.1.1.1.4 InitializeBinding ( name, value )

a Declarative Environment Record envRecord의 구체 메서드 InitializeBinding. 인수 name (String) 및 value (ECMAScript 언어 값). 반환값: 정상 완료 (값: unused). 이 메서드는 이름이 name인 식별자의 현재 바인딩 값을 value 값으로 설정하는 데 사용됩니다. name에 대한 초기화되지 않은 바인딩이 이미 존재해야 합니다. 호출되면 다음 단계를 수행한다.

  1. 단언: envRecord에는 name에 대한 초기화되지 않은 바인딩이 있어야 합니다.
  2. envRecord에서 name의 바인딩된 값을 value로 설정합니다.
  3. envRecord에서 name에 대한 바인딩이 초기화되었음을 기록합니다.
  4. unused를 반환합니다.

9.1.1.1.5 SetMutableBinding ( name, value, strict )

a Declarative Environment Record envRecord의 구체 메서드 SetMutableBinding. 인수 name (String), value (ECMAScript 언어 값) 및 strict (Boolean). 반환값: (정상 완료 (값: unused) 또는 throw 완료). 이름이 name인 식별자의 현재 바인딩 값을 value 값으로 변경하려고 시도합니다. 일반적으로 name에 대한 바인딩이 이미 존재하지만 드문 경우에는 존재하지 않을 수 있습니다. 바인딩이 변경 불가능한 바인딩이고 strict가 true이면 TypeError를 던집니다. 호출되면 다음 단계를 수행한다.

  1. envRecord에 name에 대한 바인딩이 없으면, 다음을 수행합니다.
    1. strict가 true이면, ReferenceError 예외를 던집니다.
    2. ! envRecord.CreateMutableBinding(name, true)를 수행합니다.
    3. ! envRecord.InitializeBinding(name, value)을 수행합니다.
    4. unused를 반환합니다.
  2. envRecord에서 name에 대한 바인딩이 엄격 바인딩이면 strict를 true로 설정합니다.
  3. envRecord에서 name에 대한 바인딩이 아직 초기화되지 않았으면, 다음을 수행합니다.
    1. ReferenceError 예외를 던집니다.
  4. 그렇지 않고 envRecord에서 name에 대한 바인딩이 변경 가능한 바인딩이면, 다음을 수행합니다.
    1. 해당 바인딩 값을 value로 변경합니다.
  5. 그렇지 않으면,
    1. 단언: 이는 변경 불가능한 바인딩의 값을 변경하려는 시도입니다.
    2. strict가 true이면, TypeError 예외를 던집니다.
  6. unused를 반환합니다.
참고

1 단계에서 누락된 바인딩이 발생하는 ECMAScript 코드의 예는 다음과 같습니다:

function f() { eval("var x; x = (delete x, 0);"); }

9.1.1.1.6 GetBindingValue ( name, strict )

a Declarative Environment Record envRecord의 구체 메서드 GetBindingValue. 인수 name (String) 및 strict (Boolean). 반환값: (정상 완료 (값: ECMAScript 언어 값) 또는 throw 완료). 이름이 name인 바인딩된 식별자의 값을 반환합니다. 바인딩은 존재하지만 초기화되지 않았으면 strict 값과 관계없이 ReferenceError를 던집니다. 호출되면 다음 단계를 수행한다.

  1. 단언: envRecord에는 name에 대한 바인딩이 있습니다.
  2. envRecord에서 name에 대한 바인딩이 초기화되지 않은 바인딩이면, ReferenceError 예외를 던집니다.
  3. 현재 envRecord에서 name에 바인딩된 값을 반환합니다.

9.1.1.1.7 DeleteBinding ( name )

a Declarative Environment Record envRecord의 구체 메서드 DeleteBinding. 인수 name (String). 반환값: 정상 완료 (값: Boolean). 명시적으로 삭제 가능 대상으로 지정된 바인딩만 삭제할 수 있습니다. 호출되면 다음 단계를 수행한다.

  1. 단언: envRecord에는 name에 대한 바인딩이 있습니다.
  2. name에 대한 바인딩을 삭제할 수 없으면, false를 반환합니다.
  3. envRecord에서 name에 대한 바인딩을 제거합니다.
  4. true를 반환합니다.

9.1.1.1.8 HasThisBinding ( )

a Declarative Environment Record envRecord의 구체 메서드 HasThisBinding. 인수 없음. 반환값: false. 호출되면 다음 단계를 수행한다.

  1. false를 반환합니다.
참고

일반적인 Declarative Environment Record(즉, Function Environment Record도 Module Environment Record도 아닌 Record)는 this 바인딩을 제공하지 않습니다.

9.1.1.1.9 GetThisBinding ( )

Declarative Environment Record의 GetThisBinding 구체 메서드는 이 명세에서 절대로 사용되지 않습니다.

9.1.1.1.10 HasSuperBinding ( )

a Declarative Environment Record envRecord의 구체 메서드 HasSuperBinding. 인수 없음. 반환값: false. 호출되면 다음 단계를 수행한다.

  1. false를 반환합니다.
참고

일반적인 Declarative Environment Record(즉, Function Environment Record도 Module Environment Record도 아닌 Record)는 super 바인딩을 제공하지 않습니다.

9.1.1.1.11 WithBaseObject ( )

a Declarative Environment Record envRecord의 구체 메서드 WithBaseObject. 인수 없음. 반환값: undefined. 호출되면 다음 단계를 수행한다.

  1. undefined를 반환합니다.

9.1.1.2 Object Environment Record

각 Object Environment Record는 바인딩 객체라고 하는 객체와 연결됩니다. Object Environment Record는 자신의 바인딩 객체의 프로퍼티 이름과 직접 대응하는 문자열 식별자 이름 집합을 바인딩합니다. IdentifierName 형태의 String이 아닌 프로퍼티 키는 바인딩된 식별자 집합에 포함되지 않습니다. [[Enumerable]] 속성의 설정과 관계없이 자체 프로퍼티와 상속된 프로퍼티를 모두 집합에 포함합니다. 객체에 프로퍼티를 동적으로 추가하거나 삭제할 수 있으므로 Object Environment Record가 바인딩하는 식별자 집합은 프로퍼티를 추가하거나 삭제하는 모든 연산의 부작용으로 변경될 수 있습니다. 이러한 부작용의 결과로 생성되는 모든 바인딩은 대응하는 프로퍼티의 Writable 속성이 false이더라도 변경 가능한 바인딩으로 간주합니다. Object Environment Record에는 변경 불가능한 바인딩이 존재하지 않습니다.

with 문(14.11)을 위해 생성된 Object Environment Record는 함수 호출에 사용할 암묵적인 this 값으로 자신의 바인딩 객체를 제공할 수 있습니다. 이 기능은 Boolean [[IsWithEnvironment]] 필드로 제어됩니다.

Object Environment Record에는 표 16에 나열된 추가 상태 필드가 있습니다.

표 16: Object Environment Record의 추가 필드
필드 이름 값 의미
[[BindingObject]] Object 이 Environment Record의 바인딩 객체입니다.
[[IsWithEnvironment]] Boolean 이 Environment Record가 with 문을 위해 생성되었는지를 나타냅니다.

9.1.1.2.1 HasBinding ( name )

an Object Environment Record envRecord의 구체 메서드 HasBinding. 인수 name (String). 반환값: (정상 완료 (값: Boolean) 또는 throw 완료). 연결된 바인딩 객체에 이름이 name인 프로퍼티가 있는지 결정합니다. 호출되면 다음 단계를 수행한다.

  1. bindingObj를 envRecord.[[BindingObject]]로 둡니다.
  2. foundBinding을 ? HasProperty(bindingObj, name)으로 둡니다.
  3. foundBinding이 false이면, false를 반환합니다.
  4. envRecord.[[IsWithEnvironment]]가 false이면, true를 반환합니다.
  5. unscopables를 ? Get(bindingObj, %Symbol.unscopables%)로 둡니다.
  6. unscopables가 Object이면, 다음을 수행합니다.
    1. blocked를 ToBoolean(? Get(unscopables, name))로 둡니다.
    2. blocked가 true이면, false를 반환합니다.
  7. true를 반환합니다.

9.1.1.2.2 CreateMutableBinding ( name, deletable )

an Object Environment Record envRecord의 구체 메서드 CreateMutableBinding. 인수 name (String) 및 deletable (Boolean). 반환값: (정상 완료 (값: unused) 또는 throw 완료). Environment Record와 연결된 바인딩 객체에 이름이 name인 프로퍼티를 생성하고 undefined 값으로 초기화합니다. deletable이 true이면 새 프로퍼티의 [[Configurable]] 속성을 true로 설정하고, 그렇지 않으면 false로 설정합니다. 호출되면 다음 단계를 수행한다.

  1. bindingObj를 envRecord.[[BindingObject]]로 둡니다.
  2. ? DefinePropertyOrThrow(bindingObj, name, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: deletable })를 수행합니다.
  3. unused를 반환합니다.
참고

일반적으로 envRecord에는 name에 대한 바인딩이 없지만, 바인딩이 있는 경우 DefinePropertyOrThrow의 의미론에 따라 기존 바인딩이 교체되거나 가려지거나 비정상 완료가 반환될 수 있습니다.

9.1.1.2.3 CreateImmutableBinding ( name, strict )

Object Environment Record의 CreateImmutableBinding 구체 메서드는 이 명세에서 절대로 사용되지 않습니다.

9.1.1.2.4 InitializeBinding ( name, value )

an Object Environment Record envRecord의 구체 메서드 InitializeBinding. 인수 name (String) 및 value (ECMAScript 언어 값). 반환값: (정상 완료 (값: unused) 또는 throw 완료). 이름이 name인 식별자의 현재 바인딩 값을 value 값으로 설정하는 데 사용됩니다. 호출되면 다음 단계를 수행한다.

  1. ? envRecord.SetMutableBinding(name, value, false)를 수행합니다.
  2. unused를 반환합니다.
참고

이 명세에서 Object Environment Record에 대한 CreateMutableBinding의 모든 사용은 같은 이름에 대한 InitializeBinding 호출이 바로 뒤따릅니다. 따라서 이 명세에서는 Object Environment Record의 바인딩 초기화 상태를 명시적으로 추적하지 않습니다.

9.1.1.2.5 SetMutableBinding ( name, value, strict )

an Object Environment Record envRecord의 구체 메서드 SetMutableBinding. 인수 name (String), value (ECMAScript 언어 값) 및 strict (Boolean). 반환값: (정상 완료 (값: unused) 또는 throw 완료). Environment Record와 연결된 바인딩 객체에서 이름이 name인 프로퍼티 값을 value 값으로 설정하려고 시도합니다. 일반적으로 name이라는 프로퍼티가 이미 존재하지만, 존재하지 않거나 현재 쓰기 가능하지 않은 경우 오류 처리는 strict에 따라 결정됩니다. 호출되면 다음 단계를 수행한다.

  1. bindingObj를 envRecord.[[BindingObject]]로 둡니다.
  2. stillExists를 ? HasProperty(bindingObj, name)으로 둡니다.
  3. stillExists가 false이고 strict가 true이면, ReferenceError 예외를 던집니다.
  4. ? Set(bindingObj, name, value, strict)를 수행합니다.
  5. unused를 반환합니다.

9.1.1.2.6 GetBindingValue ( name, strict )

an Object Environment Record envRecord의 구체 메서드 GetBindingValue. 인수 name (String) 및 strict (Boolean). 반환값: (정상 완료 (값: ECMAScript 언어 값) 또는 throw 완료). 연결된 바인딩 객체에서 이름이 name인 프로퍼티의 값을 반환합니다. 해당 프로퍼티는 이미 존재해야 하지만 존재하지 않는 경우 결과는 strict에 따라 달라집니다. 호출되면 다음 단계를 수행한다.

  1. bindingObj를 envRecord.[[BindingObject]]로 둡니다.
  2. value를 ? HasProperty(bindingObj, name)으로 둡니다.
  3. value가 false이면, 다음을 수행합니다.
    1. strict가 false이면, undefined를 반환합니다.
    2. ReferenceError 예외를 던집니다.
  4. ? Get(bindingObj, name)을 반환합니다.

9.1.1.2.7 DeleteBinding ( name )

an Object Environment Record envRecord의 구체 메서드 DeleteBinding. 인수 name (String). 반환값: (정상 완료 (값: Boolean) 또는 throw 완료). 환경 객체의 [[Configurable]] 속성 값이 true인 프로퍼티에 대응하는 바인딩만 삭제할 수 있습니다. 호출되면 다음 단계를 수행한다.

  1. bindingObj를 envRecord.[[BindingObject]]로 둡니다.
  2. ? bindingObj.[[Delete]](name)을 반환합니다.

9.1.1.2.8 HasThisBinding ( )

an Object Environment Record envRecord의 구체 메서드 HasThisBinding. 인수 없음. 반환값: false. 호출되면 다음 단계를 수행한다.

  1. false를 반환합니다.
참고

Object Environment Record는 this 바인딩을 제공하지 않습니다.

9.1.1.2.9 GetThisBinding ( )

Object Environment Record의 GetThisBinding 구체 메서드는 이 명세에서 절대로 사용되지 않습니다.

9.1.1.2.10 HasSuperBinding ( )

an Object Environment Record envRecord의 구체 메서드 HasSuperBinding. 인수 없음. 반환값: false. 호출되면 다음 단계를 수행한다.

  1. false를 반환합니다.
참고

Object Environment Record는 super 바인딩을 제공하지 않습니다.

9.1.1.2.11 WithBaseObject ( )

an Object Environment Record envRecord의 구체 메서드 WithBaseObject. 인수 없음. 반환값: (Object 또는 undefined). 호출되면 다음 단계를 수행한다.

  1. envRecord.[[IsWithEnvironment]]가 true이면, envRecord.[[BindingObject]]를 반환합니다.
  2. undefined를 반환합니다.

9.1.1.3 Function Environment Record

Function Environment Record는 함수의 최상위 스코프를 나타내는 데 사용하는 Declarative Environment Record이며, 함수가 ArrowFunction 함수 또는 AsyncArrowFunction 함수가 아니면 this 바인딩을 제공합니다. 함수가 ArrowFunction 함수 또는 AsyncArrowFunction 함수가 아니고 super를 참조하면, 해당 Function Environment Record에는 함수 내부에서 super 메서드 호출을 수행하는 데 사용하는 상태도 포함됩니다.

Function Environment Record에는 표 17에 나열된 추가 상태 필드가 있습니다.

표 17: Function Environment Record의 추가 필드
필드 이름 값 의미
[[ThisValue]] ECMAScript 언어 값 이 함수 호출에 사용하는 this 값입니다.
[[ThisBindingStatus]] lexical, initialized 또는 uninitialized 값이 lexical이면 이는 ArrowFunction 또는 AsyncArrowFunction이며 로컬 this 값을 갖지 않습니다.
[[FunctionObject]] ECMAScript 함수 객체 호출됨으로써 이 Environment Record가 생성된 함수 객체입니다.
[[NewTarget]] 생성자 또는 undefined 이 Environment Record가 [[Construct]] 내부 메서드에 의해 생성되었으면 [[NewTarget]]은 [[Construct]]의 newTarget 매개변수 값입니다. 그렇지 않으면 값은 undefined입니다.

Function Environment Record는 표 15에 나열된 모든 Declarative Environment Record 메서드를 지원하며, HasThisBinding, GetThisBinding 및 HasSuperBinding을 제외한 모든 메서드에 대해 동일한 명세를 공유합니다.

9.1.1.3.1 BindThisValue ( envRecord, value )

추상 연산 BindThisValue. 인수 envRecord (Function Environment 레코드) 및 value (ECMAScript 언어 값). 반환값: (정상 완료 (값: unused) 또는 throw 완료). envRecord.[[ThisValue]]를 설정하고 초기화되었음을 기록합니다. 호출되면 다음 단계를 수행한다.

  1. 단언: envRecord.[[ThisBindingStatus]]는 lexical이 아닙니다.
  2. envRecord.[[ThisBindingStatus]]가 initialized이면, ReferenceError 예외를 던집니다.
  3. envRecord.[[ThisValue]]를 value로 설정합니다.
  4. envRecord.[[ThisBindingStatus]]를 initialized로 설정합니다.
  5. unused를 반환합니다.

9.1.1.3.2 HasThisBinding ( )

a Function Environment Record envRecord의 구체 메서드 HasThisBinding. 인수 없음. 반환값: Boolean. 호출되면 다음 단계를 수행한다.

  1. envRecord.[[ThisBindingStatus]]가 lexical이면, false를 반환합니다.
  2. true를 반환합니다.

9.1.1.3.3 GetThisBinding ( )

a Function Environment Record envRecord의 구체 메서드 GetThisBinding. 인수 없음. 반환값: (정상 완료 (값: ECMAScript 언어 값) 또는 throw 완료). 호출되면 다음 단계를 수행한다.

  1. 단언: envRecord.[[ThisBindingStatus]]는 lexical이 아닙니다.
  2. envRecord.[[ThisBindingStatus]]가 uninitialized이면, ReferenceError 예외를 던집니다.
  3. envRecord.[[ThisValue]]를 반환합니다.

9.1.1.3.4 HasSuperBinding ( )

a Function Environment Record envRecord의 구체 메서드 HasSuperBinding. 인수 없음. 반환값: Boolean. 호출되면 다음 단계를 수행한다.

  1. envRecord.[[ThisBindingStatus]]가 lexical이면, false를 반환합니다.
  2. envRecord.[[FunctionObject]].[[HomeObject]]가 undefined이면, false를 반환합니다.
  3. true를 반환합니다.

9.1.1.3.5 GetSuperBase ( envRecord )

추상 연산 GetSuperBase. 인수 envRecord (Function Environment 레코드). 반환값: (Object, null 또는 undefined). envRecord에 바인딩된 super 프로퍼티 접근의 기반이 되는 객체를 반환합니다. undefined 값은 이러한 접근이 런타임 오류를 생성함을 나타냅니다. 호출되면 다음 단계를 수행한다.

  1. home을 envRecord.[[FunctionObject]].[[HomeObject]]로 둡니다.
  2. home이 undefined이면, undefined를 반환합니다.
  3. 단언: home은 일반 객체입니다.
  4. ! home.[[GetPrototypeOf]]()를 반환합니다.

9.1.1.4 Global Environment Record

Global Environment Record는 공통 realm에서 처리되는 모든 ECMAScript Script 요소가 공유하는 가장 바깥쪽 스코프를 나타내는 데 사용됩니다. Global Environment Record는 내장 전역(절 19), 전역 객체의 프로퍼티 및 Script 내에서 발생하는 모든 최상위 선언(8.2.11, 8.2.13)에 대한 바인딩을 제공합니다.

Global Environment Record는 논리적으로 하나의 Record이지만, Object Environment Record와 Declarative Environment Record를 캡슐화한 복합체로 명시됩니다. Object Environment Record는 연결된 Realm Record의 전역 객체를 기반 객체로 갖습니다. 이 전역 객체는 Global Environment Record의 GetThisBinding 구체 메서드가 반환하는 값입니다. Global Environment Record의 Object Environment Record 구성 요소에는 모든 내장 전역(절 19)에 대한 바인딩과 전역 코드에 포함된 FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration, AsyncGeneratorDeclaration 또는 VariableStatement가 도입한 모든 바인딩이 포함됩니다. 전역 코드에 있는 그 밖의 모든 ECMAScript 선언에 대한 바인딩은 Global Environment Record의 Declarative Environment Record 구성 요소에 포함됩니다.

프로퍼티는 전역 객체에 직접 생성될 수 있습니다. 따라서 Global Environment Record의 Object Environment Record 구성 요소에는 FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration, AsyncGeneratorDeclaration 또는 VariableDeclaration 선언에 의해 명시적으로 생성된 바인딩과 전역 객체의 프로퍼티로서 암묵적으로 생성된 바인딩이 모두 포함될 수 있습니다.

Global Environment Record에는 표 18에 나열된 추가 필드가 있습니다.

표 18: Global Environment Record의 추가 필드
필드 이름 값 의미
[[ObjectRecord]] Object Environment Record 바인딩 객체는 전역 객체입니다. 연결된 realm의 전역 코드에서 전역 내장 바인딩뿐만 아니라 FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration, AsyncGeneratorDeclaration 및 VariableDeclaration 바인딩을 포함합니다.
[[GlobalThisValue]] Object 전역 스코프에서 this가 반환하는 값입니다. 호스트는 임의의 ECMAScript Object 값을 제공할 수 있습니다.
[[DeclarativeRecord]] Declarative Environment Record 연결된 realm 코드의 전역 코드에 있는 모든 선언에 대한 바인딩을 포함합니다. 단, FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration, AsyncGeneratorDeclaration 및 VariableDeclaration 바인딩은 제외합니다.

9.1.1.4.1 HasBinding ( name )

a Global Environment Record envRecord의 구체 메서드 HasBinding. 인수 name (String). 반환값: (정상 완료 (값: Boolean) 또는 throw 완료). 인수 식별자가 해당 Record에 의해 바인딩된 식별자 중 하나인지 결정합니다. 호출되면 다음 단계를 수행한다.

  1. declRecord를 envRecord.[[DeclarativeRecord]]로 둡니다.
  2. ! declRecord.HasBinding(name)이 true이면, true를 반환합니다.
  3. objRecord를 envRecord.[[ObjectRecord]]로 둡니다.
  4. ? objRecord.HasBinding(name)을 반환합니다.

9.1.1.4.2 CreateMutableBinding ( name, deletable )

a Global Environment Record envRecord의 구체 메서드 CreateMutableBinding. 인수 name (String) 및 deletable (Boolean). 반환값: (정상 완료 (값: unused) 또는 throw 완료). 초기화되지 않은 이름 name에 대한 새로운 변경 가능한 바인딩을 생성합니다. 바인딩은 연결된 DeclarativeRecord에 생성됩니다. DeclarativeRecord에는 name에 대한 바인딩이 이미 존재해서는 안 됩니다. deletable이 true이면 새 바인딩을 삭제 가능 대상으로 표시합니다. 호출되면 다음 단계를 수행한다.

  1. declRecord를 envRecord.[[DeclarativeRecord]]로 둡니다.
  2. ! declRecord.HasBinding(name)이 true이면, TypeError 예외를 던집니다.
  3. ! declRecord.CreateMutableBinding(name, deletable)을 반환합니다.

9.1.1.4.3 CreateImmutableBinding ( name, strict )

a Global Environment Record envRecord의 구체 메서드 CreateImmutableBinding. 인수 name (String) 및 strict (Boolean). 반환값: (정상 완료 (값: unused) 또는 throw 완료). 초기화되지 않은 이름 name에 대한 새로운 변경 불가능한 바인딩을 생성합니다. 이 Environment Record에는 name에 대한 바인딩이 이미 존재해서는 안 됩니다. strict가 true이면 새 바인딩을 엄격 바인딩으로 표시합니다. 호출되면 다음 단계를 수행한다.

  1. declRecord를 envRecord.[[DeclarativeRecord]]로 둡니다.
  2. ! declRecord.HasBinding(name)이 true이면, TypeError 예외를 던집니다.
  3. ! declRecord.CreateImmutableBinding(name, strict)을 반환합니다.

9.1.1.4.4 InitializeBinding ( name, value )

a Global Environment Record envRecord의 구체 메서드 InitializeBinding. 인수 name (String) 및 value (ECMAScript 언어 값). 반환값: (정상 완료 (값: unused) 또는 throw 완료). 이름이 name인 식별자의 현재 바인딩 값을 value 값으로 설정하는 데 사용됩니다. name에 대한 초기화되지 않은 바인딩이 이미 존재해야 합니다. 호출되면 다음 단계를 수행한다.

  1. declRecord를 envRecord.[[DeclarativeRecord]]로 둡니다.
  2. ! declRecord.HasBinding(name)이 true이면, 다음을 수행합니다.
    1. ! declRecord.InitializeBinding(name, value)을 반환합니다.
  3. 단언: 바인딩이 존재하면 Object Environment Record에 있어야 합니다.
  4. objRecord를 envRecord.[[ObjectRecord]]로 둡니다.
  5. ? objRecord.InitializeBinding(name, value)을 반환합니다.

9.1.1.4.5 SetMutableBinding ( name, value, strict )

a Global Environment Record envRecord의 구체 메서드 SetMutableBinding. 인수 name (String), value (ECMAScript 언어 값) 및 strict (Boolean). 반환값: (정상 완료 (값: unused) 또는 throw 완료). 이름이 name인 식별자의 현재 바인딩 값을 value 값으로 변경하려고 시도합니다. 바인딩이 변경 불가능한 바인딩이고 strict가 true이면 TypeError를 던집니다. 일반적으로 name이라는 바인딩이 이미 존재하지만, 존재하지 않거나 현재 쓰기 가능하지 않은 경우 오류 처리는 strict에 따라 결정됩니다. 호출되면 다음 단계를 수행한다.

  1. declRecord를 envRecord.[[DeclarativeRecord]]로 둡니다.
  2. ! declRecord.HasBinding(name)이 true이면, 다음을 수행합니다.
    1. ? declRecord.SetMutableBinding(name, value, strict)을 반환합니다.
  3. objRecord를 envRecord.[[ObjectRecord]]로 둡니다.
  4. ? objRecord.SetMutableBinding(name, value, strict)을 반환합니다.

9.1.1.4.6 GetBindingValue ( name, strict )

a Global Environment Record envRecord의 구체 메서드 GetBindingValue. 인수 name (String) 및 strict (Boolean). 반환값: (정상 완료 (값: ECMAScript 언어 값) 또는 throw 완료). 이름이 name인 바인딩된 식별자의 값을 반환합니다. 바인딩이 초기화되지 않은 바인딩이면 ReferenceError 예외를 던집니다. 일반적으로 name이라는 바인딩이 이미 존재하지만, 존재하지 않거나 현재 쓰기 가능하지 않은 경우 오류 처리는 strict에 따라 결정됩니다. 호출되면 다음 단계를 수행한다.

  1. declRecord를 envRecord.[[DeclarativeRecord]]로 둡니다.
  2. ! declRecord.HasBinding(name)이 true이면, 다음을 수행합니다.
    1. ? declRecord.GetBindingValue(name, strict)을 반환합니다.
  3. objRecord를 envRecord.[[ObjectRecord]]로 둡니다.
  4. ? objRecord.GetBindingValue(name, strict)을 반환합니다.

9.1.1.4.7 DeleteBinding ( name )

a Global Environment Record envRecord의 구체 메서드 DeleteBinding. 인수 name (String). 반환값: (정상 완료 (값: Boolean) 또는 throw 완료). 명시적으로 삭제 가능 대상으로 지정된 바인딩만 삭제할 수 있습니다. 호출되면 다음 단계를 수행한다.

  1. declRecord를 envRecord.[[DeclarativeRecord]]로 둡니다.
  2. ! declRecord.HasBinding(name)이 true이면, 다음을 수행합니다.
    1. ! declRecord.DeleteBinding(name)을 반환합니다.
  3. objRecord를 envRecord.[[ObjectRecord]]로 둡니다.
  4. globalObj를 objRecord.[[BindingObject]]로 둡니다.
  5. existingProperty를 ? HasOwnProperty(globalObj, name)으로 둡니다.
  6. existingProperty가 true이면, 다음을 수행합니다.
    1. ? objRecord.DeleteBinding(name)을 반환합니다.
  7. true를 반환합니다.

9.1.1.4.8 HasThisBinding ( )

a Global Environment Record envRecord의 구체 메서드 HasThisBinding. 인수 없음. 반환값: true. 호출되면 다음 단계를 수행한다.

  1. true를 반환합니다.
참고

Global Environment Record는 항상 this 바인딩을 제공합니다.

9.1.1.4.9 GetThisBinding ( )

a Global Environment Record envRecord의 구체 메서드 GetThisBinding. 인수 없음. 반환값: 정상 완료 (값: Object). 호출되면 다음 단계를 수행한다.

  1. envRecord.[[GlobalThisValue]]를 반환합니다.

9.1.1.4.10 HasSuperBinding ( )

a Global Environment Record envRecord의 구체 메서드 HasSuperBinding. 인수 없음. 반환값: false. 호출되면 다음 단계를 수행한다.

  1. false를 반환합니다.
참고

Global Environment Record는 super 바인딩을 제공하지 않습니다.

9.1.1.4.11 WithBaseObject ( )

a Global Environment Record envRecord의 구체 메서드 WithBaseObject. 인수 없음. 반환값: undefined. 호출되면 다음 단계를 수행한다.

  1. undefined를 반환합니다.

9.1.1.4.12 HasLexicalDeclaration ( envRecord, name )

추상 연산 HasLexicalDeclaration. 인수 envRecord (Global Environment 레코드) 및 name (String). 반환값: Boolean. 인수 식별자에 LexicalDeclaration 또는 ClassDeclaration과 같은 렉시컬 선언을 사용하여 생성된 envRecord 내 바인딩이 있는지 결정합니다. 호출되면 다음 단계를 수행한다.

  1. declRecord를 envRecord.[[DeclarativeRecord]]로 둡니다.
  2. ! declRecord.HasBinding(name)을 반환합니다.

9.1.1.4.13 HasRestrictedGlobalProperty ( envRecord, name )

추상 연산 HasRestrictedGlobalProperty. 인수 envRecord (Global Environment 레코드) 및 name (String). 반환값: (정상 완료 (값: Boolean) 또는 throw 완료). 인수 식별자가 전역 렉시컬 바인딩으로 가려져서는 안 되는 전역 객체 프로퍼티의 이름인지 결정합니다. 호출되면 다음 단계를 수행한다.

  1. objRecord를 envRecord.[[ObjectRecord]]로 둡니다.
  2. globalObj를 objRecord.[[BindingObject]]로 둡니다.
  3. existingProperty를 ? globalObj.[[GetOwnProperty]](name)으로 둡니다.
  4. existingProperty가 undefined이면, false를 반환합니다.
  5. existingProperty.[[Configurable]]이 true이면, false를 반환합니다.
  6. true를 반환합니다.
참고

전역 객체에는 var 또는 함수 선언을 사용해 선언하지 않고 직접 생성된 프로퍼티가 존재할 수 있습니다. 전역 객체의 구성 불가능한 프로퍼티와 같은 이름을 갖는 전역 렉시컬 바인딩은 생성할 수 없습니다. 전역 프로퍼티 "undefined"는 이러한 프로퍼티의 예입니다.

9.1.1.4.14 CanDeclareGlobalVar ( envRecord, name )

추상 연산 CanDeclareGlobalVar. 인수 envRecord (Global Environment 레코드) 및 name (String). 반환값: (정상 완료 (값: Boolean) 또는 throw 완료). 동일한 인수 name으로 대응하는 CreateGlobalVarBinding 호출을 수행했을 때 성공할지를 결정합니다. 중복 var 선언과 기존 전역 객체 프로퍼티에 대한 var 선언은 허용됩니다. 호출되면 다음 단계를 수행한다.

  1. objRecord를 envRecord.[[ObjectRecord]]로 둡니다.
  2. globalObj를 objRecord.[[BindingObject]]로 둡니다.
  3. hasProperty를 ? HasOwnProperty(globalObj, name)으로 둡니다.
  4. hasProperty가 true이면, true를 반환합니다.
  5. ? IsExtensible(globalObj)을 반환합니다.

9.1.1.4.15 CanDeclareGlobalFunction ( envRecord, name )

추상 연산 CanDeclareGlobalFunction. 인수 envRecord (Global Environment 레코드) 및 name (String). 반환값: (정상 완료 (값: Boolean) 또는 throw 완료). 동일한 인수 name으로 대응하는 CreateGlobalFunctionBinding 호출을 수행했을 때 성공할지를 결정합니다. 호출되면 다음 단계를 수행한다.

  1. objRecord를 envRecord.[[ObjectRecord]]로 둡니다.
  2. globalObj를 objRecord.[[BindingObject]]로 둡니다.
  3. existingProperty를 ? globalObj.[[GetOwnProperty]](name)으로 둡니다.
  4. existingProperty가 undefined이면, ? IsExtensible(globalObj)을 반환합니다.
  5. existingProperty.[[Configurable]]이 true이면, true를 반환합니다.
  6. IsDataDescriptor(existingProperty)가 true이고 existingProperty가 속성 값 { [[Writable]]: true, [[Enumerable]]: true }를 가지면, true를 반환합니다.
  7. false를 반환합니다.

9.1.1.4.16 CreateGlobalVarBinding ( envRecord, name, deletable )

추상 연산 CreateGlobalVarBinding. 인수 envRecord (Global Environment 레코드), name (String) 및 deletable (Boolean). 반환값: (정상 완료 (값: unused) 또는 throw 완료). 연결된 Object Environment Record에 변경 가능한 바인딩을 생성하고 초기화합니다. 바인딩이 이미 존재하면 이를 재사용하며 초기화된 것으로 간주합니다. 호출되면 다음 단계를 수행한다.

  1. objRecord를 envRecord.[[ObjectRecord]]로 둡니다.
  2. globalObj를 objRecord.[[BindingObject]]로 둡니다.
  3. hasProperty를 ? HasOwnProperty(globalObj, name)으로 둡니다.
  4. extensible을 ? IsExtensible(globalObj)로 둡니다.
  5. hasProperty가 false이고 extensible이 true이면, 다음을 수행합니다.
    1. ? objRecord.CreateMutableBinding(name, deletable)를 수행합니다.
    2. ? objRecord.InitializeBinding(name, undefined)를 수행합니다.
  6. unused를 반환합니다.

9.1.1.4.17 CreateGlobalFunctionBinding ( envRecord, name, value, deletable )

추상 연산 CreateGlobalFunctionBinding. 인수 envRecord (Global Environment 레코드), name (String), value (ECMAScript 함수 객체) 및 deletable (Boolean). 반환값: (정상 완료 (값: unused) 또는 throw 완료). 연결된 Object Environment Record에 변경 가능한 바인딩을 생성하고 초기화합니다. 바인딩이 이미 존재하면 이를 교체합니다. 호출되면 다음 단계를 수행한다.

  1. objRecord를 envRecord.[[ObjectRecord]]로 둡니다.
  2. globalObj를 objRecord.[[BindingObject]]로 둡니다.
  3. existingProperty를 ? globalObj.[[GetOwnProperty]](name)으로 둡니다.
  4. existingProperty가 undefined이거나 existingProperty.[[Configurable]]이 true이면, 다음을 수행합니다.
    1. propertyDesc를 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: deletable }로 둡니다.
  5. 그렇지 않으면,
    1. propertyDesc를 PropertyDescriptor { [[Value]]: value }로 둡니다.
  6. ? DefinePropertyOrThrow(globalObj, name, propertyDesc)를 수행합니다.
  7. ? Set(globalObj, name, value, false)를 수행합니다.
  8. unused를 반환합니다.
참고

전역 함수 선언은 항상 전역 객체의 자체 프로퍼티로 나타납니다. 가능한 경우 기존 자체 프로퍼티를 표준 속성 값 집합을 갖도록 재구성합니다. 7 단계는 InitializeBinding 구체 메서드를 호출하는 것과 동등하며, globalObj가 Proxy이면 동일한 Proxy 트랩 호출 시퀀스를 생성합니다.

9.1.1.5 Module Environment Record

Module Environment Record는 ECMAScript Module의 바깥쪽 스코프를 나타내는 데 사용하는 Declarative Environment Record입니다. 일반적인 변경 가능한 바인딩과 변경 불가능한 바인딩 외에도 Module Environment Record는 다른 Environment Record에 존재하는 대상 바인딩에 대한 간접 접근을 제공하는 변경 불가능한 import 바인딩도 제공합니다.

Module Environment Record는 표 15에 나열된 모든 Declarative Environment Record 메서드를 지원하며, GetBindingValue, DeleteBinding, HasThisBinding 및 GetThisBinding을 제외한 모든 메서드에 대해 동일한 명세를 공유합니다.

9.1.1.5.1 GetBindingValue ( name, strict )

a Module Environment Record envRecord의 구체 메서드 GetBindingValue. 인수 name (String) 및 strict (Boolean). 반환값: (정상 완료 (값: ECMAScript 언어 값) 또는 throw 완료). 이름이 name인 바인딩된 식별자의 값을 반환합니다. 그러나 바인딩이 간접 바인딩이면 대상 바인딩의 값을 반환합니다. 바인딩은 존재하지만 초기화되지 않았으면 ReferenceError를 던집니다. 호출되면 다음 단계를 수행한다.

  1. 단언: strict는 true입니다.
  2. 단언: envRecord에는 name에 대한 바인딩이 있습니다.
  3. name에 대한 바인딩이 간접 바인딩이면, 다음을 수행합니다.
    1. module과 targetName을 이 name에 대한 바인딩이 생성될 때 제공된 간접 참조 값으로 둡니다.
    2. targetEnv를 module.[[Environment]]로 둡니다.
    3. targetEnv가 empty이면, ReferenceError 예외를 던집니다.
    4. ? targetEnv.GetBindingValue(targetName, true)를 반환합니다.
  4. envRecord에서 name에 대한 바인딩이 초기화되지 않은 바인딩이면, ReferenceError 예외를 던집니다.
  5. 현재 envRecord에서 name에 바인딩된 값을 반환합니다.
참고

Module은 항상 엄격 모드 코드이므로 strict는 항상 true입니다.

9.1.1.5.2 DeleteBinding ( name )

Module Environment Record의 DeleteBinding 구체 메서드는 이 명세에서 절대로 사용되지 않습니다.

참고

Module Environment Record는 엄격 코드에서만 사용되며, 조기 오류 규칙은 엄격 코드에서 delete 연산자를 Module Environment Record 바인딩으로 해석되는 Reference Record에 적용하는 것을 방지합니다. 13.5.1.1를 참조하시기 바랍니다.

9.1.1.5.3 HasThisBinding ( )

a Module Environment Record envRecord의 구체 메서드 HasThisBinding. 인수 없음. 반환값: true. 호출되면 다음 단계를 수행한다.

  1. true를 반환합니다.
참고

Module Environment Record는 항상 this 바인딩을 제공합니다.

9.1.1.5.4 GetThisBinding ( )

a Module Environment Record envRecord의 구체 메서드 GetThisBinding. 인수 없음. 반환값: 정상 완료 (값: undefined). 호출되면 다음 단계를 수행한다.

  1. undefined를 반환합니다.

9.1.1.5.5 CreateImportBinding ( envRecord, name, targetModule, targetName )

추상 연산 CreateImportBinding. 인수 envRecord (Module Environment 레코드), name (String), targetModule (Module 레코드) 및 targetName (String). 반환값: unused. 이름 name에 대해 초기화된 새로운 변경 불가능한 간접 바인딩을 생성합니다. envRecord에는 name에 대한 바인딩이 이미 존재해서는 안 됩니다. targetName은 targetModule의 Module Environment Record에 존재하는 바인딩의 이름입니다. 새 바인딩의 값에 접근하면 대상 바인딩의 바인딩된 값에 간접적으로 접근합니다. 호출되면 다음 단계를 수행한다.

  1. 단언: envRecord에는 name에 대한 바인딩이 이미 존재하지 않습니다.
  2. 단언: targetModule.[[Environment]]가 인스턴스화되면 targetName에 대한 직접 바인딩을 갖습니다.
  3. envRecord에 name에 대한 변경 불가능한 간접 바인딩을 생성하여 targetModule 및 targetName을 대상 바인딩으로 참조하게 하고, 바인딩이 초기화되었음을 기록합니다.
  4. unused를 반환합니다.

9.1.2 Environment Record 연산

다음 추상 연산은 이 명세에서 Environment Record에 대해 연산하는 데 사용됩니다:

9.1.2.1 GetIdentifierReference ( envRecord, name, strict )

추상 연산 GetIdentifierReference. 인수 envRecord ((Environment 레코드 또는 null)), name (String) 및 strict (Boolean). 반환값: (정상 완료 (값: Reference 레코드) 또는 throw 완료). 호출되면 다음 단계를 수행한다.

  1. envRecord가 null이면, 다음을 수행합니다.
    1. Reference Record { [[Base]]: unresolvable, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }를 반환합니다.
  2. exists를 ? envRecord.HasBinding(name)으로 둡니다.
  3. exists가 true이면, 다음을 수행합니다.
    1. Reference Record { [[Base]]: envRecord, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }를 반환합니다.
  4. outer를 envRecord.[[OuterEnv]]로 둡니다.
  5. ? GetIdentifierReference(outer, name, strict)를 반환합니다.

9.1.2.2 NewDeclarativeEnvironment ( outerEnv )

추상 연산 NewDeclarativeEnvironment. 인수 outerEnv ((Environment 레코드 또는 null)). 반환값: Declarative Environment 레코드. 호출되면 다음 단계를 수행한다.

  1. envRecord를 바인딩을 포함하지 않는 새로운 Declarative Environment Record로 둡니다.
  2. envRecord.[[OuterEnv]]를 outerEnv로 설정합니다.
  3. envRecord.[[DisposableResourceStack]]을 새로운 빈 List로 설정합니다.
  4. envRecord를 반환합니다.

9.1.2.3 NewObjectEnvironment ( obj, isWithEnv, outerEnv )

추상 연산 NewObjectEnvironment. 인수 obj (Object), isWithEnv (Boolean) 및 outerEnv ((Environment 레코드 또는 null)). 반환값: Object Environment 레코드. 호출되면 다음 단계를 수행한다.

  1. envRecord를 새로운 Object Environment Record로 둡니다.
  2. envRecord.[[BindingObject]]를 obj로 설정합니다.
  3. envRecord.[[IsWithEnvironment]]을 isWithEnv로 설정합니다.
  4. envRecord.[[OuterEnv]]를 outerEnv로 설정합니다.
  5. envRecord를 반환합니다.

9.1.2.4 NewFunctionEnvironment ( func, newTarget )

추상 연산 NewFunctionEnvironment. 인수 func (ECMAScript 함수 객체) 및 newTarget ((Object 또는 undefined)). 반환값: Function Environment 레코드. 호출되면 다음 단계를 수행한다.

  1. envRecord를 바인딩을 포함하지 않는 새로운 Function Environment Record로 둡니다.
  2. envRecord.[[FunctionObject]]를 func로 설정합니다.
  3. func.[[ThisMode]]가 lexical이면, envRecord.[[ThisBindingStatus]]를 lexical로 설정합니다.
  4. 그렇지 않으면 envRecord.[[ThisBindingStatus]]를 uninitialized로 설정합니다.
  5. envRecord.[[NewTarget]]을 newTarget으로 설정합니다.
  6. envRecord.[[OuterEnv]]를 func.[[Environment]]로 설정합니다.
  7. envRecord.[[DisposableResourceStack]]을 새로운 빈 List로 설정합니다.
  8. envRecord를 반환합니다.

9.1.2.5 NewGlobalEnvironment ( obj, thisValue )

추상 연산 NewGlobalEnvironment. 인수 obj (Object) 및 thisValue (Object). 반환값: Global Environment 레코드. 호출되면 다음 단계를 수행한다.

  1. objRecord를 NewObjectEnvironment(obj, false, null)로 둡니다.
  2. declRecord를 NewDeclarativeEnvironment(null)로 둡니다.
  3. envRecord를 새로운 Global Environment Record로 둡니다.
  4. envRecord.[[ObjectRecord]]를 objRecord로 설정합니다.
  5. envRecord.[[GlobalThisValue]]를 thisValue로 설정합니다.
  6. envRecord.[[DeclarativeRecord]]를 declRecord로 설정합니다.
  7. envRecord.[[OuterEnv]]를 null로 설정합니다.
  8. envRecord를 반환합니다.

9.1.2.6 NewModuleEnvironment ( outerEnv )

추상 연산 NewModuleEnvironment. 인수 outerEnv (Global Environment 레코드). 반환값: Module Environment 레코드. 호출되면 다음 단계를 수행한다.

  1. envRecord를 바인딩을 포함하지 않는 새로운 Module Environment Record로 둡니다.
  2. envRecord.[[OuterEnv]]를 outerEnv로 설정합니다.
  3. envRecord.[[DisposableResourceStack]]을 새로운 빈 List로 설정합니다.
  4. envRecord를 반환합니다.

9.2 PrivateEnvironment Record

PrivateEnvironment Record는 ECMAScript 코드에서 ClassDeclaration 및 ClassExpression의 렉시컬 중첩 구조를 기반으로 Private Name을 추적하는 데 사용하는 명세 메커니즘입니다. 이는 Environment Record와 유사하지만 서로 구별됩니다. 각 PrivateEnvironment Record는 ClassDeclaration 또는 ClassExpression과 연결됩니다. 이러한 클래스가 평가될 때마다 해당 클래스에서 선언한 Private Name을 기록하기 위해 새로운 PrivateEnvironment Record가 생성됩니다.

각 PrivateEnvironment Record에는 표 19에 정의된 필드가 있습니다.

표 19: PrivateEnvironment Record 필드
필드 이름 값 타입 의미
[[OuterPrivateEnvironment]] PrivateEnvironment Record 또는 null 가장 가까운 둘러싸는 클래스의 PrivateEnvironment Record입니다. 이 PrivateEnvironment Record와 연결된 클래스가 다른 클래스 안에 포함되지 않으면 null입니다.
[[Names]] Private Name의 List 이 클래스가 선언한 Private Name입니다.

9.2.1 PrivateEnvironment Record 연산

다음 추상 연산은 이 명세에서 PrivateEnvironment Record에 대해 연산하는 데 사용됩니다:

9.2.1.1 NewPrivateEnvironment ( outerPrivateEnv )

추상 연산 NewPrivateEnvironment. 인수 outerPrivateEnv ((PrivateEnvironment 레코드 또는 null)). 반환값: PrivateEnvironment 레코드. 호출되면 다음 단계를 수행한다.

  1. names를 새로운 빈 List로 둡니다.
  2. PrivateEnvironment Record { [[OuterPrivateEnvironment]]: outerPrivateEnv, [[Names]]: names }를 반환합니다.

9.2.1.2 ResolvePrivateIdentifier ( privateEnv, identifier )

추상 연산 ResolvePrivateIdentifier. 인수 privateEnv (PrivateEnvironment 레코드) 및 identifier (String). 반환값: 비공개 이름. 호출되면 다음 단계를 수행한다.

  1. names를 privateEnv.[[Names]]로 둡니다.
  2. names의 각 Private Name privateName에 대해 다음을 수행합니다.
    1. privateName.[[Description]]이 identifier이면, 다음을 수행합니다.
      1. privateName을 반환합니다.
  3. outerPrivateEnv를 privateEnv.[[OuterPrivateEnvironment]]로 둡니다.
  4. 단언: outerPrivateEnv는 null이 아닙니다.
  5. ResolvePrivateIdentifier(outerPrivateEnv, identifier)를 반환합니다.

9.3 Realm

모든 ECMAScript 코드는 평가되기 전에 realm과 연결되어야 합니다. 개념적으로 realm은 내재 객체 집합, ECMAScript 전역 환경, 해당 전역 환경의 스코프 내에서 로드된 모든 ECMAScript 코드 및 기타 연결된 상태와 리소스로 구성됩니다.

realm은 이 명세에서 표 20에 명시된 필드를 갖는 Realm Record로 나타냅니다:

표 20: Realm Record 필드
필드 이름 값 의미
[[AgentSignifier]] 에이전트 식별자 이 realm을 소유하는 에이전트
[[Intrinsics]] 필드 이름이 내재 키이고 값이 객체인 Record 이 realm과 연결된 코드가 사용하는 내재 값
[[GlobalObject]] Object 이 realm의 전역 객체
[[GlobalEnv]] Global Environment Record 이 realm의 전역 환경
[[TemplateMap]] [[Site]](TemplateLiteral Parse Node) 및 [[Array]](Array) 필드를 갖는 Record의 List

템플릿 객체는 각 realm의 Realm Record [[TemplateMap]]을 사용하여 realm별로 별도로 정규화됩니다. 각 [[Site]] 값은 TemplateLiteral인 Parse Node입니다. 연결된 [[Array]] 값은 태그 함수에 전달되는 대응하는 템플릿 객체입니다.

참고 1
Parse Node에 더 이상 접근할 수 없게 되면 대응하는 [[Array]]에도 접근할 수 없게 되며, 구현체가 [[TemplateMap]] 목록에서 해당 쌍을 제거하더라도 관찰할 수 없습니다.
[[LoadedModules]] LoadedModuleRequest Record의 List

이 realm이 가져온 지정자 문자열에서 해석된 Module Record로의 매핑입니다. 이 목록에는 ModuleRequestsEqual(r1, r2)가 true인 서로 다른 두 Record r1과 r2가 포함되지 않습니다.

참고 2
HostLoadImportedModule(16.2.1.10 참고 1)에서 언급했듯이 Realm Record의 [[LoadedModules]]는 활성 스크립트 또는 모듈이 없는 문맥에서 import() 표현식을 실행할 때만 사용됩니다.
[[HostDefined]] 임의의 값(기본값은 undefined) Realm Record에 추가 정보를 연결해야 하는 호스트가 사용하도록 예약된 필드입니다.

9.3.1 InitializeHostDefinedRealm ( )

추상 연산 InitializeHostDefinedRealm. 인수 없음. 반환값: (정상 완료 (값: unused) 또는 throw 완료). 호출되면 다음 단계를 수행한다.

  1. realm을 새로운 Realm Record로 둡니다.
  2. CreateIntrinsics(realm)를 수행합니다.
  3. realm.[[AgentSignifier]]을 AgentSignifier()로 설정합니다.
  4. realm.[[TemplateMap]]을 새로운 빈 List로 설정합니다.
  5. newContext를 새로운 실행 컨텍스트로 둡니다.
  6. newContext의 Function을 null로 설정합니다.
  7. newContext의 Realm을 realm으로 설정합니다.
  8. newContext의 ScriptOrModule을 null로 설정합니다.
  9. newContext를 실행 컨텍스트 스택에 푸시합니다. 이제 newContext가 실행 중인 실행 컨텍스트입니다.
  10. 호스트가 realm의 전역 객체로 사용할 특정 객체를 요구하면, 다음을 수행합니다.
    1. global을 호스트 정의 방식으로 생성한 해당 객체로 둡니다.
  11. 그렇지 않으면,
    1. global을 OrdinaryObjectCreate(realm.[[Intrinsics]].[[%Object.prototype%]])로 둡니다.
  12. 호스트가 realm의 전역 스코프에서 this 바인딩이 전역 객체가 아닌 객체를 반환하도록 요구하면, 다음을 수행합니다.
    1. thisValue를 호스트 정의 방식으로 생성한 해당 객체로 둡니다.
  13. 그렇지 않으면,
    1. thisValue를 global로 둡니다.
  14. realm.[[GlobalObject]]를 global로 설정합니다.
  15. realm.[[GlobalEnv]]를 NewGlobalEnvironment(global, thisValue)로 설정합니다.
  16. ? SetDefaultGlobalBindings(realm)를 수행합니다.
  17. global에 호스트 정의 전역 객체 프로퍼티를 생성합니다.
  18. unused를 반환합니다.

9.3.2 CreateIntrinsics ( realmRecord )

추상 연산 CreateIntrinsics. 인수 realmRecord (Realm 레코드). 반환값: unused. 호출되면 다음 단계를 수행한다.

  1. realmRecord.[[Intrinsics]]를 새로운 Record로 설정합니다.
  2. realmRecord.[[Intrinsics]]의 필드를 표 6에 나열된 값으로 설정합니다. 필드 이름은 표의 “Intrinsic Name” 열에 나열된 이름입니다. 각 필드의 값은 절 19부터 28까지 각 객체의 명세에 정의된 프로퍼티 값으로 완전히 재귀적으로 채워진 새로운 객체 값입니다. 모든 객체 프로퍼티 값은 새로 생성된 객체 값입니다. 내장 함수 객체인 모든 값은 CreateBuiltinFunction(steps, length, name, slots, realmRecord, proto, async)을 수행하여 생성합니다. 여기에서 steps는 이 명세가 제공하는 해당 함수의 정의이고, name은 함수의 "name" 프로퍼티 초기값이며, length는 함수의 "length" 프로퍼티 초기값이고, slots는 지정된 함수 내부 슬롯 이름의 목록이며(있는 경우), proto는 함수의 [[Prototype]] 내부 슬롯에 지정된 값이고, async는 함수가 “async”로 설명되면 true, 그렇지 않으면 false입니다. 내재 객체와 그 프로퍼티의 생성은 아직 생성되지 않은 객체에 대한 의존성이 발생하지 않도록 순서를 정해야 합니다.
  3. AddRestrictedFunctionProperties(realmRecord.[[Intrinsics]].[[%Function.prototype%]], realmRecord)를 수행합니다.
  4. unused를 반환합니다.

9.3.3 SetDefaultGlobalBindings ( realmRecord )

추상 연산 SetDefaultGlobalBindings. 인수 realmRecord (Realm 레코드). 반환값: (정상 완료 (값: unused) 또는 throw 완료). 호출되면 다음 단계를 수행한다.

  1. global을 realmRecord.[[GlobalObject]]로 둡니다.
  2. 절 19에 명시된 전역 객체의 각 프로퍼티에 대해 다음을 수행합니다.
    1. name을 프로퍼티 이름의 String 값으로 둡니다.
    2. propertyDesc를 해당 프로퍼티에 지정된 속성을 포함하는, 프로퍼티에 대해 모든 필드가 채워진 데이터 Property Descriptor로 둡니다. 19.2, 19.3 또는 19.4에 나열된 프로퍼티의 경우 [[Value]] 속성의 값은 realmRecord의 대응하는 내재 객체입니다.
    3. ? DefinePropertyOrThrow(global, name, propertyDesc)를 수행합니다.
  3. unused를 반환합니다.

9.4 실행 컨텍스트

실행 컨텍스트는 ECMAScript 구현체가 코드의 런타임 평가를 추적하는 데 사용하는 명세 장치입니다. 어느 시점이든 실제로 코드를 실행 중인 실행 컨텍스트는 에이전트당 최대 하나입니다. 이를 에이전트의 실행 중인 실행 컨텍스트라고 합니다. 이 명세에서 실행 중인 실행 컨텍스트에 대한 모든 참조는 주변 에이전트의 실행 중인 실행 컨텍스트를 나타냅니다.

실행 컨텍스트 스택은 실행 컨텍스트를 추적하는 데 사용됩니다. 실행 중인 실행 컨텍스트는 항상 이 스택의 최상위 요소입니다. 현재 실행 중인 실행 컨텍스트와 연결된 실행 가능 코드에서 해당 실행 컨텍스트와 연결되지 않은 실행 가능 코드로 제어가 이전될 때마다 새로운 실행 컨텍스트가 생성됩니다. 새로 생성된 실행 컨텍스트는 스택에 푸시되어 실행 중인 실행 컨텍스트가 됩니다.

실행 컨텍스트에는 연결된 코드의 실행 진행 상황을 추적하는 데 필요한 구현체별 상태가 포함됩니다. 각 실행 컨텍스트에는 최소한 표 21에 나열된 상태 구성 요소가 있습니다.

표 21: 모든 실행 컨텍스트의 상태 구성 요소
구성 요소 목적
코드 평가 상태 이 실행 컨텍스트와 연결된 코드의 평가를 수행, 일시 중단 및 재개하는 데 필요한 모든 상태입니다.
Function 이 실행 컨텍스트가 함수 객체의 코드를 평가 중이면 이 구성 요소의 값은 해당 함수 객체입니다. 컨텍스트가 Script 또는 Module의 코드를 평가 중이면 값은 null입니다.
Realm 연결된 코드가 ECMAScript 리소스에 접근하는 Realm Record입니다.
ScriptOrModule 연결된 코드가 유래한 Module Record 또는 Script Record입니다. InitializeHostDefinedRealm에서 생성되는 최초 실행 컨텍스트처럼 원본 스크립트 또는 모듈이 없으면 값은 null입니다.

실행 중인 실행 컨텍스트에 의한 코드 평가는 이 명세에 정의된 여러 지점에서 일시 중단될 수 있습니다. 실행 중인 실행 컨텍스트가 일시 중단되면 다른 실행 컨텍스트가 실행 중인 실행 컨텍스트가 되어 자신의 코드를 평가하기 시작할 수 있습니다. 이후 어느 시점에 일시 중단된 실행 컨텍스트가 다시 실행 중인 실행 컨텍스트가 되어 이전에 일시 중단된 지점부터 코드 평가를 계속할 수 있습니다. 실행 중인 실행 컨텍스트 상태의 실행 컨텍스트 간 전환은 일반적으로 스택과 같은 후입선출 방식으로 이루어집니다. 그러나 일부 ECMAScript 기능에는 비LIFO 방식의 실행 컨텍스트 전환이 필요합니다.

실행 중인 실행 컨텍스트의 Realm 구성 요소 값은 현재 Realm Record라고도 합니다. 실행 중인 실행 컨텍스트의 Function 구성 요소 값은 활성 함수 객체라고도 합니다.

ECMAScript 코드 실행 컨텍스트에는 표 22에 나열된 추가 상태 구성 요소가 있습니다.

표 22: ECMAScript 코드 실행 컨텍스트의 추가 상태 구성 요소
구성 요소 목적
LexicalEnvironment 이 실행 컨텍스트 내의 코드가 만든 식별자 참조를 해석하는 데 사용하는 Environment Record를 식별합니다.
VariableEnvironment 이 실행 컨텍스트 내의 VariableStatement가 생성한 바인딩을 보유하는 Environment Record를 식별합니다.
PrivateEnvironment 가장 가까운 둘러싸는 클래스에서 ClassElement가 생성한 Private Name을 보유하는 PrivateEnvironment Record를 식별합니다. 둘러싸는 클래스가 없으면 null입니다.

실행 컨텍스트의 LexicalEnvironment와 VariableEnvironment 구성 요소는 항상 Environment Record입니다.

Generator의 평가를 나타내는 실행 컨텍스트에는 표 23에 나열된 추가 상태 구성 요소가 있습니다.

표 23: Generator 실행 컨텍스트의 추가 상태 구성 요소
구성 요소 목적
Generator 이 실행 컨텍스트가 평가 중인 Generator입니다.

대부분의 상황에서 이 명세의 알고리즘은 실행 중인 실행 컨텍스트(실행 컨텍스트 스택의 최상위)만 직접 조작합니다. 따라서 “LexicalEnvironment” 및 “VariableEnvironment”라는 용어를 별도의 한정 없이 사용하면 실행 중인 실행 컨텍스트의 해당 구성 요소를 가리킵니다.

실행 컨텍스트는 순수하게 명세상의 메커니즘이며 ECMAScript 구현체의 특정 산출물과 대응할 필요는 없습니다. ECMAScript 코드가 실행 컨텍스트에 직접 접근하거나 이를 관찰하는 것은 불가능합니다.

9.4.1 GetActiveScriptOrModule ( )

추상 연산 GetActiveScriptOrModule. 인수 없음. 반환값: (Script 레코드, Module 레코드 또는 null). 실행 중인 실행 컨텍스트를 기반으로 실행 중인 스크립트 또는 모듈을 결정하는 데 사용됩니다. 호출되면 다음 단계를 수행한다.

  1. 실행 컨텍스트 스택이 비어 있으면, null을 반환합니다.
  2. executionContext를 실행 컨텍스트 스택에서 ScriptOrModule 구성 요소가 null이 아닌 가장 위쪽의 실행 컨텍스트로 둡니다.
  3. 그러한 실행 컨텍스트가 존재하지 않으면, null을 반환합니다.
  4. executionContext의 ScriptOrModule을 반환합니다.

9.4.2 ResolveBinding ( name [ , envRecord ] )

추상 연산 ResolveBinding. 인수 name (String) 및 선택적 인수 envRecord ((Environment 레코드 또는 undefined)). 반환값: (정상 완료 (값: Reference 레코드) 또는 throw 완료). name의 바인딩을 결정하는 데 사용됩니다. envRecord를 사용하여 바인딩을 검색할 Environment Record를 명시적으로 제공할 수 있습니다. 호출되면 다음 단계를 수행한다.

  1. envRecord가 존재하지 않거나 envRecord가 undefined이면, 다음을 수행합니다.
    1. envRecord를 실행 중인 실행 컨텍스트의 LexicalEnvironment로 설정합니다.
  2. 단언: envRecord는 Environment Record입니다.
  3. strict를 IsStrict(평가 중인 구문 생성 규칙)으로 둡니다.
  4. ? GetIdentifierReference(envRecord, name, strict)를 반환합니다.
참고

ResolveBinding의 결과는 항상 [[ReferencedName]] 필드가 name인 Reference Record입니다.

9.4.3 GetThisEnvironment ( )

추상 연산 GetThisEnvironment. 인수 없음. 반환값: Environment 레코드. 현재 키워드 this의 바인딩을 제공하는 Environment Record를 찾습니다. 호출되면 다음 단계를 수행한다.

  1. envRecord를 실행 중인 실행 컨텍스트의 LexicalEnvironment로 둡니다.
  2. 다음을 반복합니다.
    1. exists를 envRecord.HasThisBinding()으로 둡니다.
    2. exists가 true이면, envRecord를 반환합니다.
    3. outer를 envRecord.[[OuterEnv]]로 둡니다.
    4. 단언: outer는 null이 아닙니다.
    5. envRecord를 outer로 설정합니다.
참고

환경 목록은 항상 this 바인딩을 갖는 전역 환경으로 끝나므로 2 단계의 반복은 항상 종료됩니다.

9.4.4 ResolveThisBinding ( )

추상 연산 ResolveThisBinding. 인수 없음. 반환값: (정상 완료 (값: ECMAScript 언어 값) 또는 throw 완료). 실행 중인 실행 컨텍스트의 LexicalEnvironment를 사용하여 키워드 this의 바인딩을 결정합니다. 호출되면 다음 단계를 수행한다.

  1. envRecord를 GetThisEnvironment()로 둡니다.
  2. ? envRecord.GetThisBinding()을 반환합니다.

9.4.5 GetNewTarget ( )

추상 연산 GetNewTarget. 인수 없음. 반환값: (Object 또는 undefined). 실행 중인 실행 컨텍스트의 LexicalEnvironment를 사용하여 NewTarget 값을 결정합니다. 호출되면 다음 단계를 수행한다.

  1. envRecord를 GetThisEnvironment()로 둡니다.
  2. 단언: envRecord에는 [[NewTarget]] 필드가 있습니다.
  3. envRecord.[[NewTarget]]을 반환합니다.

9.4.6 GetGlobalObject ( )

추상 연산 GetGlobalObject. 인수 없음. 반환값: Object. 현재 실행 중인 실행 컨텍스트가 사용하는 전역 객체를 반환합니다. 호출되면 다음 단계를 수행한다.

  1. currentRealm을 현재 Realm Record로 둡니다.
  2. currentRealm.[[GlobalObject]]를 반환합니다.

9.4.7 RunSuspendedContext ( context, completionRecord )

추상 연산 RunSuspendedContext. 인수 context (실행 컨텍스트) 및 completionRecord (완료 레코드). 반환값: (정상 완료 (값: (ECMAScript 언어 값 또는 unused)) 또는 중도 완료). context를 재개하고(completionRecord를 재개 값으로 전달합니다) 결과를 기다립니다. 호출되면 다음 단계를 수행한다.

  1. callerContext를 실행 중인 실행 컨텍스트로 둡니다.
  2. callerContext를 일시 중단합니다.
  3. context를 실행 컨텍스트 스택에 푸시합니다. 이제 context가 실행 중인 실행 컨텍스트입니다.
  4. context의 일시 중단된 평가를 재개합니다. 이때 completionRecord를 해당 컨텍스트를 일시 중단시킨 연산의 결과로 전달합니다. result를 재개된 계산이 전달한 Completion Record로 둡니다.
  5. 단언: 이 단계에 도달했을 때 context는 이미 실행 컨텍스트 스택에서 제거되었고 callerContext가 다시 실행 중인 실행 컨텍스트입니다.
  6. Completion(result)를 반환합니다.

9.4.8 RunCallerContext ( value )

추상 연산 RunCallerContext. 인수 value ((ECMAScript 언어 값 또는 empty)). 반환값: 완료 레코드. 호출자 컨텍스트를 재개하고(value를 재개 값으로 전달합니다), 결과가 있으면 이를 기다립니다. 호출되면 다음 단계를 수행한다.

  1. genContext를 실행 중인 실행 컨텍스트로 둡니다.
  2. genContext를 실행 컨텍스트 스택에서 제거하고 실행 컨텍스트 스택 최상위에 있는 실행 컨텍스트를 실행 중인 실행 컨텍스트로 복원합니다.
  3. callerContext를 실행 중인 실행 컨텍스트로 둡니다.
  4. NormalCompletion(value)을 전달하여 callerContext를 재개합니다.
  5. 참고: 위 단계는 제어를 callerContext로 이전하고 일시 중단합니다. 이 알고리즘의 이후 단계로 제어가 진행될 수 있는 유일한 방법은 genContext가 다시 재개되는 것이며, 이는 영원히 발생하지 않을 수도 있습니다.
  6. 단언: genContext가 실행 중인 실행 컨텍스트입니다.
  7. result를 방금 genContext가 재개될 때 사용된 Completion Record로 둡니다.
  8. Completion(result)를 반환합니다.

9.5 Job과 Job을 큐에 넣는 호스트 연산

Job은 매개변수가 없고 다른 ECMAScript 계산이 현재 진행 중이지 않을 때 ECMAScript 계산을 시작하는 Abstract Closure입니다.

Job은 특정 에이전트에서 ECMAScript 호스트 환경에 의해 실행되도록 예약됩니다. 이 명세에서는 Job을 예약하기 위한 호스트 훅 HostEnqueueGenericJob, HostEnqueueFinalizationRegistryCleanupJob, HostEnqueuePromiseJob 및 HostEnqueueTimeoutJob을 설명합니다. 이 명세의 호스트 훅은 Job 예약에 부과되는 추가 제약 조건에 따라 구성됩니다. 호스트는 Job을 예약하는 추가 추상 연산을 정의할 수 있습니다. 이러한 연산은 Job Abstract Closure와 realm(Realm Record 또는 null)을 매개변수로 받습니다. Realm Record가 제공되면 해당 연산은 제공된 realm을 소유하는 에이전트에서 미래의 어느 시점에 Job을 수행하도록 예약합니다. realm 대신 null이 제공되면 해당 Job은 ECMAScript 코드를 평가하지 않습니다. 구현은 다음 요구 사항을 준수해야 합니다:

참고 1
호스트 환경은 예약과 관련하여 모든 Job을 동일하게 취급할 필요가 없습니다. 예를 들어 웹 브라우저와 Node.js는 Promise 처리 Job을 다른 작업보다 더 높은 우선순위로 취급합니다. 향후 기능에서는 이처럼 높은 우선순위로 처리되지 않는 Job이 추가될 수 있습니다.

특정 시점에 scriptOrModule(Script Record, Module Record 또는 null)은 다음 조건이 모두 참인 경우 활성 스크립트 또는 모듈입니다:

특정 시점에 실행은 다음 조건이 모두 참이면 ECMAScript 코드를 평가할 준비가 된 상태입니다:

참고 2

호스트 환경은 실행 컨텍스트를 실행 컨텍스트 스택에 푸시하여 코드 평가를 위한 실행을 준비할 수 있습니다. 구체적인 단계는 구현체 정의입니다.

구체적으로 어떤 Realm을 선택할지는 호스트 환경이 결정합니다. 이 최초 실행 컨텍스트와 Realm은 콜백 함수가 호출되기 전까지만 사용됩니다. Promise 핸들러와 같이 Job과 관련된 콜백 함수가 호출되면 해당 호출은 자신의 실행 컨텍스트와 Realm을 푸시합니다.

특정 종류의 Job에는 추가 적합성 요구 사항이 있습니다.

9.5.1 JobCallback Record

JobCallback Record는 함수 객체와 호스트 정의 값을 저장하는 데 사용하는 Record입니다. 호스트가 큐에 넣은 Job을 통해 호출되는 함수 객체는 추가적인 호스트 정의 문맥을 가질 수 있습니다. 이 상태를 전파하기 위해 Job Abstract Closure는 함수 객체를 직접 캡처하여 호출하지 않아야 합니다. 대신 HostMakeJobCallback과 HostCallJobCallback을 사용합니다.

참고

예를 들어 WHATWG HTML 명세(https://html.spec.whatwg.org/)는 호스트 정의 값을 사용하여 Promise 콜백에 대한 incumbent settings object를 전파합니다.

JobCallback Record에는 표 24에 나열된 필드가 있습니다.

표 24: JobCallback Record 필드
필드 이름 값 의미
[[Callback]] 함수 객체 Job이 호출될 때 호출할 함수입니다.
[[HostDefined]] 임의의 값(기본값은 empty) 호스트가 사용하도록 예약된 필드입니다.

9.5.2 HostMakeJobCallback ( callback )

호스트 정의 추상 연산 HostMakeJobCallback. 인수 callback (함수 객체). 반환값: JobCallback 레코드.

HostMakeJobCallback의 구현은 다음 요구 사항을 준수해야 합니다:

HostMakeJobCallback의 기본 구현은 호출될 때 다음 단계를 수행합니다:

  1. JobCallback Record { [[Callback]]: callback, [[HostDefined]]: empty }를 반환합니다.

웹 브라우저가 아닌 ECMAScript 호스트는 HostMakeJobCallback의 기본 구현을 사용해야 합니다.

참고

이는 콜백이 나중에 예약되어 실행되도록 하는 함수에 전달되는 시점에 호출됩니다. 예를 들어 promise.then(thenAction)은 반응 Job을 예약하는 시점이 아니라 Promise.prototype.then을 호출하는 시점에 thenAction에 대해 MakeJobCallback을 호출합니다.

9.5.3 HostCallJobCallback ( jobCallback, thisValue, argList )

호스트 정의 추상 연산 HostCallJobCallback. 인수 jobCallback (JobCallback 레코드), thisValue (ECMAScript 언어 값) 및 argList (리스트 (요소: ECMAScript 언어 값)). 반환값: (정상 완료 (값: ECMAScript 언어 값) 또는 throw 완료).

HostCallJobCallback의 구현은 다음 요구 사항을 준수해야 합니다:

  • Call(jobCallback.[[Callback]], thisValue, argList)을 수행하고 그 결과를 반환해야 합니다.
참고

이 요구 사항은 호스트가 이 명세에 정의된 함수 객체의 [[Call]] 동작을 변경할 수 없음을 의미합니다.

HostCallJobCallback의 기본 구현은 호출될 때 다음 단계를 수행합니다:

  1. 단언: IsCallable(jobCallback.[[Callback]])은 true입니다.
  2. ? Call(jobCallback.[[Callback]], thisValue, argList)을 반환합니다.

웹 브라우저가 아닌 ECMAScript 호스트는 HostCallJobCallback의 기본 구현을 사용해야 합니다.

9.5.4 HostEnqueueGenericJob ( job, realm )

호스트 정의 추상 연산 HostEnqueueGenericJob. 인수 job (a Job Abstract Closure) 및 realm (Realm 레코드). 반환값: unused. realm.[[AgentSignifier]]로 나타내는 에이전트에서 미래의 어느 시점에 수행되도록 realm realm에 job을 예약합니다. 이 알고리즘과 함께 사용하는 Abstract Closure는 우선순위나 순서와 같은 추가 제약 조건 없이 예약되도록 의도되었습니다.

HostEnqueueGenericJob의 구현은 9.5의 요구 사항을 준수해야 합니다.

9.5.5 HostEnqueuePromiseJob ( job, realm )

호스트 정의 추상 연산 HostEnqueuePromiseJob. 인수 job (a Job Abstract Closure) 및 realm ((Realm 레코드 또는 null)). 반환값: unused. 미래의 어느 시점에 수행되도록 job을 예약합니다. 이 알고리즘과 함께 사용하는 Abstract Closure는 Promise 처리와 관련되거나 그 밖에 Promise 처리 연산과 같은 우선순위로 예약되도록 의도되었습니다.

HostEnqueuePromiseJob의 구현은 9.5의 요구 사항뿐만 아니라 다음 사항도 준수해야 합니다:

  • realm이 null이 아니면 job이 호출될 때마다 구현체는 job 호출 시점에 실행이 ECMAScript 코드를 평가할 준비가 되도록 구현체 정의 단계를 수행해야 합니다.
  • HostEnqueuePromiseJob이 호출되는 시점의 GetActiveScriptOrModule()을 scriptOrModule로 둡니다. realm이 null이 아니면 job이 호출될 때마다 구현체는 job 호출 시점에 scriptOrModule이 활성 스크립트 또는 모듈이 되도록 구현체 정의 단계를 수행해야 합니다.
  • Job은 이를 예약한 HostEnqueuePromiseJob 호출과 동일한 순서로 실행되어야 합니다.
참고

NewPromiseResolveThenableJob이 반환한 Job의 realm은 일반적으로 then 함수 객체에 대해 GetFunctionRealm을 호출한 결과입니다. NewPromiseReactionJob이 반환한 Job의 realm은 핸들러가 undefined가 아니면 일반적으로 핸들러에 대해 GetFunctionRealm을 호출한 결과입니다. 핸들러가 undefined이면 realm은 null입니다. 두 종류의 Job 모두 GetFunctionRealm이 비정상적으로 완료되면(즉, 해제된 Proxy에서 호출된 경우) realm은 GetFunctionRealm 호출 시점의 현재 Realm Record입니다. realm이 null이면 사용자 ECMAScript 코드는 평가되지 않고 새로운 ECMAScript 객체(예: Error 객체)도 생성되지 않습니다. 예를 들어 WHATWG HTML 명세(https://html.spec.whatwg.org/)는 realm을 사용하여 스크립트를 실행할 수 있는지와 entry 개념을 검사합니다.

9.5.6 HostEnqueueTimeoutJob ( timeoutJob, realm, milliseconds )

호스트 정의 추상 연산 HostEnqueueTimeoutJob. 인수 timeoutJob (a Job Abstract Closure), realm (Realm 레코드) 및 milliseconds (음이 아닌 유한한 Number). 반환값: unused. realm.[[AgentSignifier]]로 나타내는 에이전트에서 최소 milliseconds밀리초 후에 수행되도록 realm realm에 timeoutJob을 예약합니다.

HostEnqueueTimeoutJob의 구현은 9.5의 요구 사항을 준수해야 합니다.

9.6 에이전트

에이전트는 ECMAScript 실행 컨텍스트의 집합, 실행 컨텍스트 스택, 실행 중인 실행 컨텍스트, Agent Record 및 실행 스레드로 구성됩니다. 실행 스레드를 제외한 에이전트의 구성 요소는 해당 에이전트에만 속합니다.

에이전트의 실행 스레드는 다른 에이전트와 독립적으로 해당 에이전트의 실행 컨텍스트에서 알고리즘 단계를 실행합니다. 단, 스레드를 공유하는 에이전트 중 [[CanBlock]] 필드가 true인 Agent Record를 갖는 에이전트가 없다면 하나의 실행 스레드를 여러 에이전트의 실행 스레드로 사용할 수 있습니다.

참고 1

예를 들어 일부 웹 브라우저는 브라우저 창의 관련 없는 여러 탭 사이에서 하나의 실행 스레드를 공유합니다.

에이전트의 실행 스레드가 알고리즘 단계를 실행하는 동안 해당 에이전트는 그 단계의 주변 에이전트입니다. 단계는 주변 에이전트를 사용하여 에이전트가 보유하는 명세 수준 실행 객체, 즉 실행 중인 실행 컨텍스트, 실행 컨텍스트 스택 및 Agent Record의 필드에 접근합니다.

에이전트 식별자는 Agent를 식별하는 데 사용하는 전역적으로 고유한 불투명 값입니다.

표 25: Agent Record 필드
필드 이름 값 의미
[[LittleEndian]] Boolean GetValueFromBuffer 및 SetValueInBuffer 알고리즘에서 isLittleEndian 매개변수가 필요할 때 계산되는 기본값입니다. 선택은 구현체 정의이며 구현체에 가장 효율적인 대안을 사용해야 합니다.
[[CanBlock]] Boolean 에이전트가 블로킹될 수 있는지를 결정합니다.
[[Signifier]] 에이전트 식별자 에이전트 클러스터 내에서 에이전트를 고유하게 식별합니다.
[[IsLockFree1]] Boolean 1바이트 값에 대한 원자적 연산이 lock-free이면 true, 그렇지 않으면 false입니다.
[[IsLockFree2]] Boolean 2바이트 값에 대한 원자적 연산이 lock-free이면 true, 그렇지 않으면 false입니다.
[[IsLockFree8]] Boolean 8바이트 값에 대한 원자적 연산이 lock-free이면 true, 그렇지 않으면 false입니다.
[[CandidateExecution]] 후보 실행 Record 메모리 모델을 참조하시기 바랍니다.
[[KeptAlive]] Object 또는 Symbol의 List 처음에는 새로운 빈 List이며, 현재 Job이 끝날 때까지 생존 상태로 유지할 객체 및/또는 Symbol의 목록을 나타냅니다.
[[ModuleAsyncEvaluationCount]] 정수 처음에는 0이며, 비동기이거나 비동기 의존성을 갖는 모듈의 [[AsyncEvaluationOrder]] 필드에 증가하는 고유 값을 할당하는 데 사용됩니다.
[[GlobalSymbolRegistry]] GlobalSymbolRegistry Record의 List 처음에는 새로운 빈 List이며, Symbol.for가 생성한 Symbol 값의 목록을 나타냅니다.

[[LittleEndian]], [[Signifier]], [[IsLockFree1]], [[IsLockFree2]] 및 [[IsLockFree8]]의 값은 변경될 수 없습니다.

[[GlobalSymbolRegistry]] List는 추가만 가능하며 다시 할당되지 않습니다.

참고 2

[[IsLockFree1]], [[IsLockFree2]] 및 [[IsLockFree8]]의 값은 반드시 하드웨어에 의해 결정되는 것은 아니며, 시간에 따라 또는 ECMAScript 구현체마다 달라질 수 있는 구현 선택을 반영할 수도 있습니다.

[[IsLockFree4]] 필드는 없습니다. 4바이트 원자적 연산은 항상 lock-free입니다.

실제로 어떤 형태의 락을 사용하여 원자적 연산을 구현하면 해당 연산은 lock-free가 아닙니다. lock-free가 wait-free를 의미하지는 않습니다. lock-free 원자적 연산을 완료하는 데 필요한 머신 단계 수에는 상한이 없습니다.

크기가 n인 원자적 접근이 lock-free라는 사실은 크기가 n인 비원자적 접근의 (인지되는) 원자성에 대해 아무것도 의미하지 않습니다. 특히 비원자적 접근은 여전히 여러 개의 별도 메모리 접근 시퀀스로 수행될 수 있습니다. 자세한 내용은 ReadSharedMemory 및 WriteSharedMemory를 참조하시기 바랍니다.

참고 3

에이전트는 명세상의 메커니즘이며 ECMAScript 구현체의 특정 산출물과 대응할 필요는 없습니다.

9.6.1 AgentSignifier ( )

추상 연산 AgentSignifier. 인수 없음. 반환값: an agent signifier. 호출되면 다음 단계를 수행한다.

  1. agentRecord를 주변 에이전트의 Agent Record로 둡니다.
  2. agentRecord.[[Signifier]]을 반환합니다.

9.6.2 AgentCanSuspend ( )

추상 연산 AgentCanSuspend. 인수 없음. 반환값: Boolean. 호출되면 다음 단계를 수행한다.

  1. agentRecord를 주변 에이전트의 Agent Record로 둡니다.
  2. agentRecord.[[CanBlock]]을 반환합니다.
참고

일부 환경에서는 특정 에이전트가 일시 중단되는 것이 합리적이지 않을 수 있습니다. 예를 들어 웹 브라우저 환경에서는 문서의 주 이벤트 처리 스레드가 일시 중단되는 것은 허용하지 않으면서 worker의 이벤트 처리 스레드는 일시 중단할 수 있도록 하는 것이 합리적일 수 있습니다.

9.6.3 IncrementModuleAsyncEvaluationCount ( )

추상 연산 IncrementModuleAsyncEvaluationCount. 인수 없음. 반환값: 음이 아닌 정수. 호출되면 다음 단계를 수행한다.

  1. agentRecord를 주변 에이전트의 Agent Record로 둡니다.
  2. count를 agentRecord.[[ModuleAsyncEvaluationCount]]로 둡니다.
  3. agentRecord.[[ModuleAsyncEvaluationCount]]를 count + 1로 설정합니다.
  4. count를 반환합니다.
참고

이 값은 보류 중인 모듈 사이의 상대적인 평가 순서를 추적하는 데만 사용됩니다. 보류 중인 모듈이 없을 때 구현체는 관찰할 수 없는 방식으로 [[ModuleAsyncEvaluationCount]]를 0으로 재설정할 수 있습니다.

9.7 에이전트 클러스터

에이전트 클러스터는 공유 메모리에서 연산하여 서로 통신할 수 있는 에이전트의 극대 집합입니다.

참고 1

서로 다른 에이전트의 프로그램은 명시되지 않은 수단으로 메모리를 공유할 수 있습니다. 최소한 SharedArrayBuffer의 기반 메모리는 클러스터의 에이전트 사이에서 공유할 수 있습니다.

메시지 전달을 통해 통신할 수 있지만 메모리를 공유할 수 없는 에이전트가 있을 수 있으며, 이러한 에이전트는 절대로 같은 에이전트 클러스터에 있지 않습니다.

모든 에이전트는 정확히 하나의 에이전트 클러스터에 속합니다.

참고 2

클러스터의 모든 에이전트가 특정 시점에 동시에 생존해 있을 필요는 없습니다. 에이전트 A가 다른 에이전트 B를 생성한 뒤 A가 종료되고, B가 에이전트 C를 생성하는 경우, A가 B와 일부 메모리를 공유할 수 있고 B가 C와 일부 메모리를 공유할 수 있었다면 세 에이전트는 같은 클러스터에 있습니다.

클러스터 내의 모든 에이전트는 각자의 Agent Record에 있는 [[LittleEndian]] 필드에 대해 동일한 값을 가져야 합니다.

참고 3

에이전트 클러스터 내의 서로 다른 에이전트가 서로 다른 [[LittleEndian]] 값을 가지면 다중 바이트 데이터에 공유 메모리를 사용하기 어려워집니다.

클러스터 내의 모든 에이전트는 각자의 Agent Record에 있는 [[IsLockFree1]] 필드에 대해 동일한 값을 가져야 하며, [[IsLockFree2]] 및 [[IsLockFree8]] 필드도 마찬가지입니다.

클러스터 내의 모든 에이전트는 각자의 Agent Record에 있는 [[Signifier]] 필드에 서로 다른 값을 가져야 합니다.

임베딩은 에이전트의 인지나 협조 없이 에이전트를 비활성화(전진 진행 중지)하거나 활성화(전진 진행 재개)할 수 있습니다. 임베딩이 이를 수행하는 경우 클러스터 내 일부 에이전트는 활성 상태로 둔 채 다른 에이전트를 무기한 비활성화 상태로 두어서는 안 됩니다.

참고 4

앞의 제한은 다른 에이전트가 비활성화되었기 때문에 어떤 에이전트가 교착되거나 기아 상태에 빠지는 상황을 방지하기 위한 것입니다. 예를 들어 어떤 창의 문서와 독립적인 수명을 갖는 HTML shared worker가 그러한 독립 문서의 dedicated worker와 메모리를 공유할 수 있고, dedicated worker가 락을 보유한 상태에서 문서와 해당 dedicated worker가 비활성화된 후(예: 문서가 창의 방문 기록에 들어간 경우) shared worker가 해당 락을 획득하려고 시도한다면, shared worker는 dedicated worker가 다시 활성화될 때까지, 어쩌면 영원히, 블로킹됩니다. 그동안 다른 창에서 shared worker에 접근하려는 다른 worker는 기아 상태에 빠집니다.

이 제한의 결과로 임베딩 내부에서 동일한 suspend/wake 집합에 속하지 않는 에이전트 사이에서는 메모리를 공유할 수 없습니다.

임베딩은 에이전트 클러스터의 다른 에이전트가 사전에 알거나 협조하지 않아도 에이전트를 종료할 수 있습니다. 에이전트가 자신 또는 클러스터 내 다른 에이전트의 프로그램적 동작이 아니라 클러스터 외부의 요인으로 종료되면, 임베딩은 두 전략 중 하나를 선택해야 합니다. 클러스터의 모든 에이전트를 종료하거나, 클러스터의 에이전트가 협력하여 최소 하나의 남은 구성원이 종료를 감지할 수 있도록 신뢰할 수 있는 API를 제공해야 하며, 종료 데이터에는 종료된 에이전트를 식별하기에 충분한 정보가 포함되어야 합니다.

참고 5

이러한 종료의 예로는 운영 체제나 사용자가 별도 프로세스에서 실행 중인 에이전트를 종료하는 경우, 또는 에이전트별 리소스 계측 결과 해당 에이전트가 폭주 중임을 나타내어 임베딩 자체가 다른 에이전트와 같은 프로세스에서 실행 중인 에이전트를 종료하는 경우가 있습니다.

다음의 각 명세 값과 그 값에서 전이적으로 도달 가능한 값은 정확히 하나의 에이전트 클러스터에 속합니다.

클러스터의 임의의 에이전트가 ECMAScript 코드를 평가하기 전에, 클러스터 내 모든 에이전트의 Agent Record에 있는 [[CandidateExecution]] 필드는 초기 후보 실행으로 설정됩니다. 초기 후보 실행은 [[EventsRecords]] 필드가 각 에이전트마다 하나씩 Agent Events Record를 포함하는 List인 빈 후보 실행입니다. 각 Agent Events Record의 [[AgentSignifier]] 필드는 해당 에이전트의 에이전트 식별자이며, [[EventList]]와 [[AgentSynchronizesWith]] 필드는 빈 List입니다.

참고 6

에이전트 클러스터의 모든 에이전트는 Agent Record의 [[CandidateExecution]] 필드에서 동일한 후보 실행을 공유합니다. 후보 실행은 메모리 모델에서 사용하는 명세 메커니즘입니다.

참고 7

에이전트 클러스터는 명세상의 메커니즘이며 ECMAScript 구현체의 특정 산출물과 대응할 필요는 없습니다.

9.8 전진 진행

에이전트가 전진 진행을 한다는 것은 이 명세에 따라 평가 단계를 수행하는 것을 의미합니다.

에이전트의 실행 중인 실행 컨텍스트가 외부 이벤트를 동기적으로 무기한 기다리게 되면 에이전트는 블로킹 상태가 됩니다. Agent Record의 [[CanBlock]] 필드가 true인 에이전트만 이러한 의미에서 블로킹될 수 있습니다. 블로킹되지 않은 에이전트는 블로킹 상태가 아닌 에이전트입니다.

구현체는 다음을 보장해야 합니다:

참고

이 요구 사항은 메모리 모델의 생존성 보장과 함께 모든 seq-cst 쓰기가 결국 모든 에이전트에서 관찰 가능해짐을 보장합니다.

9.9 WeakRef 및 FinalizationRegistry 대상의 처리 모델

9.9.1 목표

이 명세는 어떤 객체나 Symbol이 가비지 컬렉션될 것이라는 보장도 하지 않습니다. 생존하지 않는 객체나 Symbol도 오랜 시간이 지난 후 해제될 수도 있고, 전혀 해제되지 않을 수도 있습니다. 이러한 이유로 이 명세에서는 가비지 컬렉션에 의해 발생하는 동작을 설명할 때 “할 수 있습니다”라는 표현을 사용합니다.

WeakRef 및 FinalizationRegistry의 의미론은 특정 시점에 발생하는 두 연산을 기반으로 합니다:

이 두 동작(ClearKeptObjects 또는 CleanupFinalizationRegistry)은 모두 동기 ECMAScript 실행을 중단시켜서는 안 됩니다. 호스트가 더 긴 동기 ECMAScript 실행 구간을 구성할 수 있으므로 이 명세에서는 ClearKeptObjects 및 CleanupFinalizationRegistry의 예약을 호스트 환경에 위임합니다.

일부 ECMAScript 구현체에는 ECMAScript가 유휴 상태일 때를 포함하여 백그라운드에서 실행되는 가비지 컬렉터 구현이 있습니다. 호스트 환경이 CleanupFinalizationRegistry를 예약할 수 있게 하면 finalizer 작업을 실행하기 위해 ECMAScript 실행을 재개하고, 보유 중인 값을 해제하여 전체 메모리 사용량을 줄일 수 있습니다.

9.9.2 생존성

객체 및/또는 Symbol의 어떤 집합 objSet에 대해 objSet에 대한 가상의 WeakRef 비인식 실행은, 참조 대상이 objSet의 요소인 WeakRef에 대해 추상 연산 WeakRefDeref가 항상 undefined를 반환하는 실행입니다.

참고 1
WeakRef 비인식성과 생존성은 함께 두 가지 개념을 포착합니다. 첫째, WeakRef 자체는 참조 대상을 생존 상태로 유지하지 않습니다. 둘째, 생존성의 순환이 값이 생존 상태임을 의미하지는 않습니다. 구체적으로 v의 생존성 결정이 WeakRef 참조 대상 r의 생존성 결정에 의존하는 경우, r의 생존성은 v의 생존성을 가정할 수 없습니다. 그렇게 하면 순환 추론이 됩니다.
참고 2
WeakRef 비인식성은 순환을 고려하기 위해 개별 값이 아니라 객체 또는 Symbol의 집합에 대해 정의됩니다. 개별 값에 대해 정의하면 순환 안의 WeakRef 참조 대상은 그 동일성이 순환 내 다른 WeakRef 참조 대상을 통해서만 관찰되더라도 생존 상태로 간주됩니다.
참고 3
비공식적으로 개별 객체 또는 Symbol을 포함하는 모든 집합이 생존 상태이면 해당 객체 또는 Symbol도 생존 상태라고 합니다.

평가 중 어느 시점이든 객체 및/또는 Symbol의 집합 objSet은 다음 조건 중 하나라도 충족하면 생존 상태로 간주합니다:

  • objSet의 어떤 요소가 임의의 에이전트의 [[KeptAlive]] List에 포함되어 있습니다.
  • objSet에 대해, objSet의 값 중 하나의 동일성을 관찰하는 유효한 미래의 가상 WeakRef 비인식 실행이 존재합니다.
참고 4
위의 두 번째 조건은 값의 동일성을 WeakRef가 아닌 수단으로 관찰할 수 있으면 해당 값이 생존 상태라는 직관을 포착하려는 것입니다. 값의 동일성은 엄격 동등성 비교 결과를 관찰하거나 해당 값이 Map의 키로 사용되는 것을 관찰하여 확인할 수 있습니다.
참고 5

객체 또는 Symbol이 필드, 내부 슬롯 또는 프로퍼티에 존재한다고 해서 해당 값이 생존 상태임을 의미하지는 않습니다. 예를 들어 문제의 값이 프로그램에 다시 전달되지 않는다면 관찰할 수 없습니다.

이는 WeakMap의 키, WeakSet의 구성원, 그리고 FinalizationRegistry Cell Record의 [[WeakRefTarget]] 및 [[UnregisterToken]] 필드에 해당합니다.

위 정의에 따르면 WeakMap의 키가 생존 상태가 아니라면 이에 대응하는 값도 반드시 생존 상태라고 할 수는 없습니다.

참고 6
생존성은 엔진이 어떤 WeakRef를 비워서는 안 되는지를 보장하기 위한 하한입니다. 여기에서 정의한 생존성은 결정 불가능합니다. 실제로 엔진은 도달 가능성과 같은 보수적인 근사를 사용합니다. 구현에는 상당한 재량이 있을 것으로 예상됩니다.

9.9.3 실행

어느 시점이든 객체 및/또는 Symbol의 집합 objSet이 생존 상태가 아니면 ECMAScript 구현체는 다음 단계를 원자적으로 수행할 수 있습니다:

  1. objSet의 각 요소 value에 대해 다음을 수행합니다.
    1. ref.[[WeakRefTarget]]이 value인 각 WeakRef ref에 대해 다음을 수행합니다.
      1. ref.[[WeakRefTarget]]을 empty로 설정합니다.
    2. finalizationRegistry.[[Cells]]가 cell.[[WeakRefTarget]]이 value인 Record cell을 포함하는 각 FinalizationRegistry finalizationRegistry에 대해 다음을 수행합니다.
      1. cell.[[WeakRefTarget]]을 empty로 설정합니다.
      2. enqueueCleanup을 true 또는 false 중 하나를 선택하는 구현체 정의 선택으로 둡니다.
      3. enqueueCleanup이 true이면, HostEnqueueFinalizationRegistryCleanupJob(finalizationRegistry)을 수행합니다.
    3. map.[[WeakMapData]]가 entry.[[Key]]가 value인 Record entry를 포함하는 각 WeakMap map에 대해 다음을 수행합니다.
      1. entry.[[Key]]를 empty로 설정합니다.
      2. entry.[[Value]]를 empty로 설정합니다.
    4. set.[[WeakSetData]]가 value를 포함하는 각 WeakSet set에 대해 다음을 수행합니다.
      1. set.[[WeakSetData]]에서 값이 value인 요소를 값이 empty인 요소로 교체합니다.
참고 1

생존성의 정의와 함께 이 절은 구현체가 WeakRef에 적용할 수 있는 최적화를 규정합니다.

객체의 동일성을 관찰하지 않고도 객체에 접근할 수 있습니다. 동일성이 관찰되지 않는 탈출하지 않는 객체의 프로퍼티에 대해 죽은 변수 제거 및 스칼라 대체와 같은 최적화가 허용됩니다. 따라서 이러한 최적화로 해당 객체를 가리키는 WeakRef가 관찰 가능하게 비워지는 것도 허용됩니다.

반면 객체의 동일성을 관찰할 수 있고 해당 객체가 WeakRef의 [[WeakRefTarget]] 내부 슬롯에 있으면, WeakRef를 관찰 가능하게 비우는 재구체화와 같은 최적화는 금지됩니다.

HostEnqueueFinalizationRegistryCleanupJob 호출은 선택 사항이므로 FinalizationRegistry에 등록된 객체가 반드시 해당 FinalizationRegistry를 생존 상태로 유지하는 것은 아닙니다. 구현체는 어떤 이유로든 FinalizationRegistry 콜백을 생략할 수 있습니다. 예를 들어 FinalizationRegistry 자체가 생존 상태가 아니게 되거나 애플리케이션이 종료 중인 경우가 있습니다.

참고 2

구현체는 생존 상태가 아닌 객체 또는 Symbol의 최대 집합에 대해 WeakRef를 비울 의무가 없습니다.

구현체가 WeakRef를 비울 생존하지 않는 집합 objSet을 선택하면, 이 정의에 따라 objSet의 모든 값에 대한 WeakRef를 동시에 비워야 합니다. 다시 말해, 구현체가 값 v를 가리키는 WeakRef를 비우면서, 비우지 않을 경우 v의 값을 관찰하는 실행이 가능해지는 다른 WeakRef를 비우지 않는 것은 적합하지 않습니다.

9.9.4 호스트 훅

9.9.4.1 HostEnqueueFinalizationRegistryCleanupJob ( finalizationRegistry )

호스트 정의 추상 연산 HostEnqueueFinalizationRegistryCleanupJob. 인수 finalizationRegistry (FinalizationRegistry). 반환값: unused.

cleanupJob을 매개변수가 없고 finalizationRegistry를 캡처하며 호출될 때 다음 단계를 수행하는 새로운 Job Abstract Closure로 둡니다:

  1. cleanupResult를 Completion(CleanupFinalizationRegistry(finalizationRegistry))으로 둡니다.
  2. cleanupResult가 비정상 완료이면 오류 보고를 위한 호스트 정의 단계를 수행합니다.
  3. unused를 반환합니다.

HostEnqueueFinalizationRegistryCleanupJob의 구현은 가능하면 미래의 어느 시점에 수행되도록 cleanupJob을 예약합니다. 또한 9.5의 요구 사항도 준수해야 합니다.

9.10 ClearKeptObjects ( )

추상 연산 ClearKeptObjects. 인수 없음. 반환값: unused. ECMAScript 구현체는 동기 ECMAScript 실행 시퀀스가 완료될 때 ClearKeptObjects를 호출하는 것이 기대됩니다. 호출되면 다음 단계를 수행한다.

  1. agentRecord를 주변 에이전트의 Agent Record로 둡니다.
  2. agentRecord.[[KeptAlive]]를 새로운 빈 List로 설정합니다.
  3. unused를 반환합니다.

9.11 AddToKeptObjects ( value )

추상 연산 AddToKeptObjects. 인수 value ((Object 또는 Symbol)). 반환값: unused. 호출되면 다음 단계를 수행한다.

  1. agentRecord를 주변 에이전트의 Agent Record로 둡니다.
  2. value를 agentRecord.[[KeptAlive]]에 추가합니다.
  3. unused를 반환합니다.
참고
추상 연산 AddToKeptObjects가 대상 객체 또는 Symbol을 인수로 호출되면 ClearKeptObjects가 호출될 때까지 대상을 강하게 참조하는 목록에 해당 대상을 추가합니다.

9.12 CleanupFinalizationRegistry ( finalizationRegistry )

추상 연산 CleanupFinalizationRegistry. 인수 finalizationRegistry (FinalizationRegistry). 반환값: (정상 완료 (값: unused) 또는 throw 완료). 호출되면 다음 단계를 수행한다.

  1. 단언: finalizationRegistry에는 [[Cells]] 및 [[CleanupCallback]] 내부 슬롯이 있습니다.
  2. callback을 finalizationRegistry.[[CleanupCallback]]으로 둡니다.
  3. finalizationRegistry.[[Cells]]가 cell.[[WeakRefTarget]]이 empty인 Record cell을 포함하는 동안, 구현체는 다음 단계를 수행할 수 있습니다:
    1. 그러한 cell 중 하나를 선택합니다.
    2. finalizationRegistry.[[Cells]]에서 cell을 제거합니다.
    3. ? HostCallJobCallback(callback, undefined, « cell.[[HeldValue]] »)을 수행합니다.
  4. unused를 반환합니다.

9.13 CanBeHeldWeakly ( arg )

추상 연산 CanBeHeldWeakly. 인수 arg (ECMAScript 언어 값). 반환값: Boolean. arg가 약한 참조로 사용하기에 적합한 경우에만 true를 반환합니다. 약한 참조로 사용하기에 적합한 값만 WeakMap의 키, WeakSet의 요소, WeakRef의 대상 또는 FinalizationRegistry의 대상 중 하나가 될 수 있습니다. 호출되면 다음 단계를 수행한다.

  1. arg가 Object이면, true를 반환합니다.
  2. arg가 Symbol이고 KeyForSymbol(arg)이 undefined이면, true를 반환합니다.
  3. false를 반환합니다.
참고

언어 동일성이 없는 언어 값은 사전 참조 없이 만들어질 수 있으므로 약한 참조로 사용하기에 적합하지 않습니다. Symbol.for가 생성한 Symbol 값은 다른 Symbol 값과 달리 언어 동일성이 없으므로 약한 참조로 사용하기에 적합하지 않습니다. 잘 알려진 Symbol은 가비지 컬렉션되지 않을 가능성이 높지만, 수가 제한되어 있어 다양한 구현 방식으로 관리할 수 있으므로 약한 참조로 사용하기에 적합한 것으로 취급됩니다. 그러나 생존 상태인 WeakMap에서 잘 알려진 Symbol에 연결된 모든 값은 가비지 컬렉션되지 않을 가능성이 높아 구현체에서 메모리 리소스를 “누수”할 수 있습니다.