페이지 표시 설정

16 ECMAScript 언어: 스크립트와 모듈

16.1 스크립트

구문

Script : ScriptBodyopt ScriptBody : StatementList[~Yield, ~Await, ~Return]

16.1.1 Static Semantics: 조기 오류

Script : ScriptBody ScriptBody : StatementList

16.1.2 Static Semantics: ScriptIsStrict

구문 지향 연산 ScriptIsStrict. 인수 없음. 반환값: Boolean. 다음 생성 규칙별로 정의된다.

Script : ScriptBodyopt
  1. ScriptBody가 존재하고 ScriptBody의 Directive Prologue에 Use Strict Directive가 포함되어 있으면 true를 반환합니다.
  2. false를 반환합니다.

16.1.3 Runtime Semantics: 평가

Script : [empty]
  1. undefined를 반환합니다.

16.1.4 Script Record

Script Record는 평가 중인 스크립트에 관한 정보를 캡슐화합니다. 각 Script Record에는 표 35에 나열된 필드가 포함됩니다.

표 35: Script Record 필드
필드 이름 값 타입 의미
[[Realm]] a Realm Record 이 스크립트가 생성된 realm입니다.
[[ECMAScriptCode]] a Script Parse Node 이 스크립트의 소스 텍스트를 파싱한 결과입니다.
[[LoadedModules]] a List of LoadedModuleRequest Records 이 스크립트가 가져온 지정자 문자열에서 해석된 Module Record로의 맵입니다. 이 목록에는 ModuleRequestsEqual(r1, r2)이 true인 서로 다른 두 Record r1과 r2가 포함되지 않습니다.
[[HostDefined]] anything (default value is empty) 스크립트에 추가 정보를 연결해야 하는 호스트 환경에서 사용하도록 예약된 필드입니다.

16.1.5 ParseScript ( sourceText, realm, hostDefined )

추상 연산 ParseScript. 인수 sourceText ((String 또는 a sequence of Unicode code points)), realm (Realm 레코드) 및 hostDefined (임의의 값). 반환값: (Script 레코드 또는 a non-empty List of SyntaxError objects). sourceText를 Script로 파싱한 결과를 기반으로 Script Record를 생성합니다. 호출되면 다음 단계를 수행한다.

  1. script를 ParseText(sourceText, Script)로 둡니다.
  2. script가 오류의 List이면 script를 반환합니다.
  3. Script Record { [[Realm]]: realm, [[ECMAScriptCode]]: script, [[LoadedModules]]: « », [[HostDefined]]: hostDefined }를 반환합니다.
참고

구현체는 해당 스크립트 소스 텍스트에 ParseScript를 평가하기 전에 스크립트 소스 텍스트를 파싱하고 조기 오류 조건을 분석할 수 있습니다. 그러나 오류 보고는 이 명세가 실제로 해당 소스 텍스트에 ParseScript를 수행하는 시점까지 지연되어야 합니다.

16.1.6 ScriptEvaluation ( scriptRecord )

추상 연산 ScriptEvaluation. 인수 scriptRecord (Script 레코드). 반환값: (정상 완료 (값: ECMAScript 언어 값) 또는 중도 완료). 호출되면 다음 단계를 수행한다.

  1. globalEnv를 scriptRecord.[[Realm]].[[GlobalEnv]]로 둡니다.
  2. scriptContext를 새로운 ECMAScript 코드 실행 컨텍스트로 둡니다.
  3. scriptContext의 Function을 null로 설정합니다.
  4. scriptContext의 Realm을 scriptRecord.[[Realm]]으로 설정합니다.
  5. scriptContext의 ScriptOrModule을 scriptRecord로 설정합니다.
  6. scriptContext의 VariableEnvironment를 globalEnv로 설정합니다.
  7. scriptContext의 LexicalEnvironment를 globalEnv로 설정합니다.
  8. scriptContext의 PrivateEnvironment를 null로 설정합니다.
  9. 실행 중인 실행 컨텍스트를 일시 중단합니다.
  10. scriptContext를 실행 컨텍스트 스택에 푸시합니다. 이제 scriptContext가 실행 중인 실행 컨텍스트입니다.
  11. scriptNode를 scriptRecord.[[ECMAScriptCode]]로 둡니다.
  12. result를 Completion(GlobalDeclarationInstantiation(scriptNode, globalEnv))으로 둡니다.
  13. result가 정상 완료이면, 다음을 수행합니다.
    1. result를 Completion(scriptNode의 Evaluation)으로 설정합니다.
    2. result가 정상 완료이고 result.[[Value]]가 empty이면, 다음을 수행합니다.
      1. result를 NormalCompletion(undefined)으로 설정합니다.
  14. scriptContext를 일시 중단하고 실행 컨텍스트 스택에서 제거합니다.
  15. 단언: 실행 컨텍스트 스택은 비어 있지 않습니다.
  16. 이제 실행 컨텍스트 스택의 맨 위에 있는 컨텍스트를 실행 중인 실행 컨텍스트로 재개합니다.
  17. ? result를 반환합니다.

16.1.7 GlobalDeclarationInstantiation ( script, envRecord )

추상 연산 GlobalDeclarationInstantiation. 인수 script (a Script Parse Node) 및 envRecord (Global Environment 레코드). 반환값: (정상 완료 (값: unused) 또는 throw 완료). script는 실행 컨텍스트를 설정할 Script입니다. envRecord는 바인딩을 생성할 전역 환경입니다.

참고 1

스크립트를 평가하기 위한 실행 컨텍스트가 설정될 때 선언은 현재 전역 환경에 인스턴스화됩니다. 코드에서 선언된 각 전역 바인딩이 인스턴스화됩니다.

호출되면 다음 단계를 수행합니다:

  1. lexicalNames를 script의 LexicallyDeclaredNames로 둡니다.
  2. variableNames를 script의 VarDeclaredNames로 둡니다.
  3. lexicalNames의 각 요소 name에 대해 다음을 수행합니다.
    1. HasLexicalDeclaration(envRecord, name)이 true이면 SyntaxError 예외를 던집니다.
    2. hasRestrictedGlobal을 ? HasRestrictedGlobalProperty(envRecord, name)로 둡니다.
    3. 참고: 전역 var 및 function 바인딩(비엄격 직접 eval에 의해 도입되는 바인딩 제외)은 구성 불가능하므로 제한된 전역 프로퍼티입니다.
    4. hasRestrictedGlobal이 true이면 SyntaxError 예외를 던집니다.
  4. variableNames의 각 요소 name에 대해 다음을 수행합니다.
    1. HasLexicalDeclaration(envRecord, name)이 true이면 SyntaxError 예외를 던집니다.
  5. variableDecls를 script의 VarScopedDeclarations로 둡니다.
  6. funcsToInitialize를 새로운 빈 List로 둡니다.
  7. declaredFuncNames를 새로운 빈 List로 둡니다.
  8. variableDecls의 각 요소 variableDecl에 대해 List의 역순으로 다음을 수행합니다.
    1. variableDecl이 VariableDeclaration, ForBinding 또는 BindingIdentifier 중 어느 것도 아니면, 다음을 수행합니다.
      1. 단언: variableDecl은 FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration 또는 AsyncGeneratorDeclaration 중 하나입니다.
      2. 참고: 같은 이름에 함수 선언이 여러 개 있으면 마지막 선언이 사용됩니다.
      3. funcName을 variableDecl의 BoundNames의 유일한 요소로 둡니다.
      4. declaredFuncNames에 funcName이 포함되어 있지 않으면, 다음을 수행합니다.
        1. funcDefinable을 ? CanDeclareGlobalFunction(envRecord, funcName)으로 둡니다.
        2. funcDefinable이 false이면 TypeError 예외를 던집니다.
        3. funcName을 declaredFuncNames에 추가합니다.
        4. variableDecl을 funcsToInitialize의 첫 번째 요소로 삽입합니다.
  9. declaredVariableNames를 새로운 빈 List로 둡니다.
  10. variableDecls의 각 요소 variableDecl에 대해 다음을 수행합니다.
    1. variableDecl이 VariableDeclaration, ForBinding 또는 BindingIdentifier 중 하나이면, 다음을 수행합니다.
      1. variableDecl의 BoundNames의 각 String name에 대해 다음을 수행합니다.
        1. declaredFuncNames에 name이 포함되어 있지 않으면, 다음을 수행합니다.
          1. variableDefinable을 ? CanDeclareGlobalVar(envRecord, name)로 둡니다.
          2. variableDefinable이 false이면 TypeError 예외를 던집니다.
          3. declaredVariableNames에 name이 포함되어 있지 않으면, 다음을 수행합니다.
            1. name을 declaredVariableNames에 추가합니다.
  11. 참고: 전역 객체가 일반 객체이면 이 알고리즘 단계 이후에는 비정상 종료가 발생하지 않습니다. 그러나 전역 객체가 Proxy 특수 객체이면 다음 단계 중 일부에서 비정상 종료를 일으키는 동작을 나타낼 수 있습니다.
  12. Normative Optional
    호스트가 웹 브라우저이거나 그 밖의 방식으로 블록 수준 함수 선언의 웹 레거시 호환성 의미론을 지원하면, 다음을 수행합니다.
    1. strict를 script의 ScriptIsStrict로 둡니다.
    2. strict가 false이면, 다음을 수행합니다.
      1. declaredFuncOrVariableNames를 declaredFuncNames와 declaredVariableNames의 목록 연결로 둡니다.
      2. script Contains x가 true인 어떤 Block, CaseClause 또는 DefaultClause x의 StatementList에 직접 포함된 각 FunctionDeclaration funcDecl에 대해 다음을 수행합니다.
        1. funcName을 funcDecl의 BindingIdentifier의 StringValue로 둡니다.
        2. FunctionDeclaration funcDecl을 funcName을 BindingIdentifier로 갖는 VariableStatement로 바꿔도 script에 조기 오류가 발생하지 않으면, 다음을 수행합니다.
          1. HasLexicalDeclaration(envRecord, funcName)이 false이면, 다음을 수행합니다.
            1. funcDefinable을 ? CanDeclareGlobalVar(envRecord, funcName)로 둡니다.
            2. funcDefinable이 true이면, 다음을 수행합니다.
              1. 참고: funcName에 대한 var 바인딩은 여기에서 funcName이 VarDeclaredName도 아니고 다른 FunctionDeclaration의 이름도 아닌 경우에만 인스턴스화됩니다.
              2. declaredFuncOrVariableNames에 funcName이 포함되어 있지 않으면, 다음을 수행합니다.
                1. ? CreateGlobalVarBinding(envRecord, funcName, false)를 수행합니다.
                2. funcName을 declaredFuncOrVariableNames에 추가합니다.
              3. FunctionDeclaration funcDecl이 평가될 때 15.2.6에 제공된 FunctionDeclaration Evaluation 알고리즘 대신 다음 단계를 수행합니다:
                1. globalEnv를 실행 중인 실행 컨텍스트의 VariableEnvironment로 둡니다.
                2. blockEnv를 실행 중인 실행 컨텍스트의 LexicalEnvironment로 둡니다.
                3. funcObj를 ! blockEnv.GetBindingValue(funcName, false)로 둡니다.
                4. ? globalEnv.SetMutableBinding(funcName, funcObj, false)를 수행합니다.
                5. unused를 반환합니다.
  13. lexicalDecls를 script의 LexicallyScopedDeclarations로 둡니다.
  14. privateEnv를 null로 둡니다.
  15. lexicalDecls의 각 요소 lexicalDecl에 대해 다음을 수행합니다.
    1. 참고: 렉시컬하게 선언된 이름은 여기에서 인스턴스화되기만 하며 초기화되지는 않습니다.
    2. lexicalDecl의 BoundNames의 각 요소 name에 대해 다음을 수행합니다.
      1. lexicalDecl의 IsConstantDeclaration이 true이면, 다음을 수행합니다.
        1. ? envRecord.CreateImmutableBinding(name, true)를 수행합니다.
      2. 그렇지 않으면,
        1. ? envRecord.CreateMutableBinding(name, false)를 수행합니다.
  16. funcsToInitialize의 각 Parse Node funcDecl에 대해 다음을 수행합니다.
    1. funcName을 funcDecl의 BoundNames의 유일한 요소로 둡니다.
    2. funcObj를 인수 envRecord 및 privateEnv를 사용한 funcDecl의 InstantiateFunctionObject로 둡니다.
    3. ? CreateGlobalFunctionBinding(envRecord, funcName, funcObj, false)를 수행합니다.
  17. declaredVariableNames의 각 String variableName에 대해 다음을 수행합니다.
    1. ? CreateGlobalVarBinding(envRecord, variableName, false)를 수행합니다.
  18. unused를 반환합니다.
참고 2

16.1.1에 명시된 조기 오류는 하나의 Script 안에 포함된 선언에서 함수/var 선언과 let/const/class 선언 사이의 이름 충돌 및 let/const/class 바인딩의 재선언을 방지합니다. 그러나 둘 이상의 Script에 걸친 이러한 충돌과 재선언은 GlobalDeclarationInstantiation 중 런타임 오류로 검출됩니다. 그러한 오류가 하나라도 검출되면 해당 스크립트에는 어떤 바인딩도 인스턴스화되지 않습니다. 다만 전역 객체가 Proxy 특수 객체를 사용하여 정의된 경우 충돌 선언에 대한 런타임 검사가 신뢰할 수 없을 수 있으며, 그 결과 비정상 완료가 발생하고 일부 전역 선언이 인스턴스화되지 않을 수 있습니다. 이런 일이 발생하면 Script의 코드는 평가되지 않습니다.

명시적인 var 또는 함수 선언과 달리 전역 객체에 직접 생성된 프로퍼티로 인해 생긴 전역 바인딩은 let/const/class 선언에 의해 가려질 수 있습니다.

16.2 모듈

구문

Module : ModuleBodyopt ModuleBody : ModuleItemList ModuleItemList : ModuleItem ModuleItemList ModuleItem ModuleItem : ImportDeclaration ExportDeclaration StatementListItem[~Yield, +Await, ~Return] ModuleExportName : IdentifierName StringLiteral

16.2.1 모듈 의미론

16.2.1.1 Static Semantics: 조기 오류

ModuleBody : ModuleItemList 참고

중복 ExportedNames 규칙은 하나의 ModuleBody 안에 여러 export default ExportDeclaration 항목이 있으면 Syntax Error라는 것을 의미합니다. 충돌하거나 중복된 선언과 관련된 추가 오류 조건은 Module을 평가하기 전에 모듈 연결 중 검사됩니다. 이러한 오류가 하나라도 검출되면 Module은 평가되지 않습니다.

ModuleExportName : StringLiteral

16.2.1.2 Static Semantics: ImportedLocalNames ( importEntries )

추상 연산 ImportedLocalNames. 인수 importEntries (리스트 (요소: ImportEntry 레코드)). 반환값: 리스트 (요소: String). importEntries에 의해 정의된 모든 로컬 이름 바인딩의 List를 생성합니다. 호출되면 다음 단계를 수행한다.

  1. localNames를 새로운 빈 List로 둡니다.
  2. importEntries의 각 ImportEntry Record importEntry에 대해 다음을 수행합니다.
    1. importEntry.[[LocalName]]을 localNames에 추가합니다.
  3. localNames를 반환합니다.

16.2.1.3 ModuleRequest Record

ModuleRequest Record는 주어진 import 속성을 사용하여 모듈을 가져오라는 요청을 나타냅니다. 다음 필드로 구성됩니다:

표 36: ModuleRequest Record 필드
필드 이름 값 타입 의미
[[Specifier]] a String 모듈 지정자
[[Attributes]] a List of ImportAttribute Records import 속성

LoadedModuleRequest Record는 결과 Module Record와 함께 모듈을 가져오라는 요청을 나타냅니다. 표 36 표에 정의된 것과 동일한 필드에 [[Module]]이 추가됩니다:

표 37: LoadedModuleRequest Record 필드
필드 이름 값 타입 의미
[[Specifier]] a String 모듈 지정자
[[Attributes]] a List of ImportAttribute Records import 속성
[[Module]] a Module Record 이 모듈 요청에 대응하여 로드된 모듈

ImportAttribute Record는 다음 필드로 구성됩니다:

표 38: ImportAttribute Record 필드
필드 이름 값 타입 의미
[[Key]] a String 속성 키
[[Value]] a String 속성 값

16.2.1.3.1 ModuleRequestsEqual ( x, y )

추상 연산 ModuleRequestsEqual. 인수 x ((ModuleRequest 레코드 또는 LoadedModuleRequest 레코드)) 및 y ((ModuleRequest 레코드 또는 LoadedModuleRequest 레코드)). 반환값: Boolean. 호출되면 다음 단계를 수행한다.

  1. x.[[Specifier]]가 y.[[Specifier]]와 같지 않으면 false를 반환합니다.
  2. xAttrs를 x.[[Attributes]]로 둡니다.
  3. yAttrs를 y.[[Attributes]]로 둡니다.
  4. xAttrsCount를 xAttrs의 요소 수로 둡니다.
  5. yAttrsCount를 yAttrs의 요소 수로 둡니다.
  6. xAttrsCount ≠ yAttrsCount이면 false를 반환합니다.
  7. xAttrs의 각 ImportAttribute Record xAttr에 대해 다음을 수행합니다.
    1. xAttr.[[Key]]가 yAttr.[[Key]]와 같고 xAttr.[[Value]]가 yAttr.[[Value]]와 같은 ImportAttribute Record yAttr이 yAttrs에 포함되어 있지 않으면 false를 반환합니다.
  8. true를 반환합니다.

16.2.1.4 Static Semantics: ModuleRequests

구문 지향 연산 ModuleRequests. 인수 없음. 반환값: 리스트 (요소: ModuleRequest 레코드). 다음 생성 규칙별로 정의된다.

Module : [empty]
  1. 새로운 빈 List를 반환합니다.
ModuleItemList : ModuleItem
  1. ModuleItem의 ModuleRequests를 반환합니다.
ModuleItemList : ModuleItemList ModuleItem
  1. requests를 ModuleItemList의 ModuleRequests로 둡니다.
  2. additionalRequests를 ModuleItem의 ModuleRequests로 둡니다.
  3. additionalRequests의 각 ModuleRequest Record moduleRequest에 대해 다음을 수행합니다.
    1. ModuleRequestsEqual(moduleRequest, otherModuleRequest)이 true인 ModuleRequest Record otherModuleRequest가 requests에 포함되어 있지 않으면, 다음을 수행합니다.
      1. moduleRequest를 requests에 추가합니다.
  4. requests를 반환합니다.
ModuleItem : StatementListItem
  1. 새로운 빈 List를 반환합니다.
ImportDeclaration : import ImportClause FromClause ;
  1. specifier를 FromClause의 SV로 둡니다.
  2. 유일한 요소가 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }인 List를 반환합니다.
ImportDeclaration : import ImportClause FromClause WithClause ;
  1. specifier를 FromClause의 SV로 둡니다.
  2. attrs를 WithClause의 WithClauseToAttributes로 둡니다.
  3. 유일한 요소가 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attrs }인 List를 반환합니다.
ImportDeclaration : import ModuleSpecifier ;
  1. specifier를 ModuleSpecifier의 SV로 둡니다.
  2. 유일한 요소가 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }인 List를 반환합니다.
ImportDeclaration : import ModuleSpecifier WithClause ;
  1. specifier를 ModuleSpecifier의 SV로 둡니다.
  2. attrs를 WithClause의 WithClauseToAttributes로 둡니다.
  3. 유일한 요소가 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attrs }인 List를 반환합니다.
ExportDeclaration : export ExportFromClause FromClause ;
  1. specifier를 FromClause의 SV로 둡니다.
  2. 유일한 요소가 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }인 List를 반환합니다.
ExportDeclaration : export ExportFromClause FromClause WithClause ;
  1. specifier를 FromClause의 SV로 둡니다.
  2. attrs를 WithClause의 WithClauseToAttributes로 둡니다.
  3. 유일한 요소가 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attrs }인 List를 반환합니다.
ExportDeclaration : export NamedExports ; export VariableStatement export Declaration export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 새로운 빈 List를 반환합니다.

16.2.1.5 추상 Module Record

Module Record는 하나의 모듈이 가져오고 내보내는 항목에 관한 구조적 정보를 캡슐화합니다. 이 정보는 서로 연결된 모듈 집합의 import와 export를 연결하는 데 사용됩니다. Module Record에는 모듈을 평가할 때만 사용하는 네 개의 필드가 포함됩니다.

명세를 위한 목적으로 Module Record는 Record 명세 타입의 값이며, Module Record가 추상 클래스이고 추상 및 구체 하위 클래스를 모두 갖는 단순한 객체 지향 계층 구조에 존재한다고 생각할 수 있습니다. 이 명세는 Cyclic Module Record라는 추상 하위 클래스와 그 구체 하위 클래스인 Source Text Module Record를 정의합니다. 다른 명세와 구현체는 자신들이 정의한 대체 모듈 정의 기능에 대응하는 추가 Module Record 하위 클래스를 정의할 수 있습니다.

Module Record는 표 39에 나열된 필드를 정의합니다. 모든 Module Definition 하위 클래스는 최소한 이러한 필드를 포함합니다. Module Record는 또한 표 40의 추상 메서드 목록을 정의합니다. 모든 Module definition 하위 클래스는 이러한 추상 메서드의 구체 구현을 제공해야 합니다.

표 39: Module Record 필드
필드 이름 값 타입 의미
[[Realm]] a Realm Record 이 모듈이 생성된 Realm입니다.
[[Environment]] a Module Environment Record or empty 이 모듈의 최상위 바인딩을 포함하는 Environment Record입니다. 이 필드는 모듈이 연결될 때 설정됩니다.
[[Namespace]] an Object or empty 이 모듈에 대해 생성된 경우 Module Namespace Object(28.3)입니다.
[[HostDefined]] anything (default value is undefined) 모듈에 추가 정보를 연결해야 하는 호스트 환경에서 사용하도록 예약된 필드입니다.
표 40: Module Records의 추상 메서드
메서드 목적 정의
LoadRequestedModules ( [ hostDefined ] )

추상 메서드 LoadRequestedModules. 선택적 인수 hostDefined (임의의 값). 반환값: Promise.

모든 종속성을 재귀적으로 로드하여 모듈을 연결할 준비를 합니다.

이 명세에서는 다음 타입에 정의가 있으며, 호스트는 자체 정의를 갖는 추가 타입을 제공할 수 있습니다:
GetExportedNames ( [ exportStarSet ] )

추상 메서드 GetExportedNames. 선택적 인수 exportStarSet (리스트 (요소: Source Text Module 레코드)). 반환값: 리스트 (요소: String).

이 모듈에서 직접 또는 간접으로 내보내는 모든 이름의 목록을 반환합니다.

이 메서드를 호출하기 전에 LoadRequestedModules가 성공적으로 완료되어 있어야 합니다.

이 명세에서는 다음 타입에 정의가 있으며, 호스트는 자체 정의를 갖는 추가 타입을 제공할 수 있습니다:
ResolveExport ( exportName [ , resolveSet ] )

추상 메서드 ResolveExport. 인수 exportName (String) 및 선택적 인수 resolveSet (리스트 (요소: 레코드 (필드: [[Module]] (Module 레코드), [[ExportName]] (String)))). 반환값: (ResolvedBinding 레코드, null 또는 ambiguous).

이 모듈에서 내보낸 이름의 바인딩을 반환합니다. 바인딩은 { [[Module]]: Module Record, [[BindingName]]: String | namespace } 형태의 ResolvedBinding Record로 나타냅니다. export가 어떤 모듈에도 직접 바인딩이 없는 Module Namespace Object이면 [[BindingName]]은 namespace로 설정됩니다. 이름을 해석할 수 없으면 null을 반환하고 여러 바인딩이 발견되면 ambiguous를 반환합니다.

이 연산을 특정 exportName, resolveSet 쌍을 인수로 사용하여 호출할 때마다 동일한 결과를 반환해야 합니다.

이 메서드를 호출하기 전에 LoadRequestedModules가 성공적으로 완료되어 있어야 합니다.

이 명세에서는 다음 타입에 정의가 있으며, 호스트는 자체 정의를 갖는 추가 타입을 제공할 수 있습니다:
Evaluate ( )

추상 메서드 Evaluate. 인수 없음. 반환값: Promise.

이 모듈과 그 종속성의 평가에 대한 promise를 반환합니다. 평가가 성공하거나 이미 성공적으로 평가된 경우 resolve되고, 평가 오류가 발생하거나 이미 평가에 실패한 경우 reject됩니다. promise가 reject되면 호스트는 promise rejection을 처리하고 평가 오류를 다시 던질 것으로 예상됩니다. 이 모듈이 Cyclic Module Record가 아닌 한 반환된 promise는 이미 settle되어 있어야 합니다.

이 메서드를 호출하기 전에 Link가 성공적으로 완료되어 있어야 합니다.

이 명세에서는 다음 타입에 정의가 있으며, 호스트는 자체 정의를 갖는 추가 타입을 제공할 수 있습니다:

16.2.1.5.1 EvaluateModuleSync ( module )

추상 연산 EvaluateModuleSync. 인수 module (Module 레코드). 반환값: (정상 완료 (값: unused) 또는 throw 완료). 호출자가 module의 평가가 이미 settle된 promise를 반환할 것임을 보장하는 경우 module을 동기적으로 평가합니다. 호출되면 다음 단계를 수행한다.

  1. 단언: module은 Cyclic Module Record가 아닙니다.
  2. promise를 module.Evaluate()로 둡니다.
  3. 단언: promise.[[PromiseState]]는 fulfilled 또는 rejected입니다.
  4. promise.[[PromiseState]]가 rejected이면, 다음을 수행합니다.
    1. promise.[[PromiseIsHandled]]가 false이면 HostPromiseRejectionTracker(promise, "handle")를 수행합니다.
    2. promise.[[PromiseIsHandled]]를 true로 설정합니다.
    3. promise.[[PromiseResult]]를 던집니다.
  5. unused를 반환합니다.

16.2.1.6 Cyclic Module Record

Cyclic Module Record는 Cyclic Module Record 타입의 하위 클래스인 다른 모듈과 종속성 순환에 참여할 수 있는 모듈에 관한 정보를 나타내는 데 사용됩니다. Cyclic Module Record 타입의 하위 클래스가 아닌 Module Record는 Source Text Module Record와의 종속성 순환에 참여해서는 안 됩니다.

표 39에 정의된 필드 외에도 Cyclic Module Record에는 표 41에 나열된 추가 필드가 있습니다.

표 41: Cyclic Module Record의 추가 필드
필드 이름 값 타입 의미
[[Status]] new, unlinked, linking, linked, evaluating, evaluating-async, or evaluated 처음에는 new입니다. 모듈이 수명 주기를 진행하면서 unlinked, linking, linked, evaluating, 경우에 따라 evaluating-async, evaluated 순서로 전이합니다. evaluating-async는 이 모듈이 비동기 종속성 완료 시 실행 대기 중이거나 [[HasTLA]] 필드가 true인 모듈로서 실행되었지만 최상위 완료를 기다리고 있음을 나타냅니다.
[[EvaluationError]] a throw completion or empty 평가 중 발생한 예외를 나타내는 throw 완료입니다. 예외가 발생하지 않았거나 [[Status]]가 evaluated가 아니면 empty입니다.
[[DFSAncestorIndex]] an integer or empty Link 및 Evaluate 중에만 사용하는 보조 필드입니다. [[Status]]가 linking 또는 evaluating이면 이 값은 모듈 자체의 깊이 우선 탐색 인덱스 또는 동일한 강연결 요소에 있는 “더 앞선” 모듈의 인덱스입니다.
[[RequestedModules]] a List of ModuleRequest Records 이 모듈의 import와 연결된 ModuleRequest Record의 List입니다. List는 import가 소스 텍스트에 나타나는 순서입니다.
[[LoadedModules]] a List of LoadedModuleRequest Records 이 Record가 나타내는 모듈이 상대 import 속성과 함께 모듈을 가져오도록 요청하는 데 사용한 지정자 문자열에서 해석된 Module Record로의 맵입니다. 이 목록에는 ModuleRequestsEqual(r1, r2)이 true인 서로 다른 두 Record r1과 r2가 포함되지 않습니다.
[[CycleRoot]] a Cyclic Module Record or empty 순환에서 처음 방문한 모듈, 즉 강연결 요소의 루트 DFS 조상입니다. 순환에 속하지 않는 모듈에서는 모듈 자신입니다. Evaluate가 완료되면 모듈의 [[DFSAncestorIndex]]는 해당 [[CycleRoot]]의 깊이 우선 탐색 인덱스입니다.
[[HasTLA]] a Boolean 이 모듈 자체가 비동기인지 여부입니다(예: 최상위 await를 포함하는 Source Text Module Record). 비동기 종속성을 갖는다고 해서 이 필드가 true인 것은 아닙니다. 이 필드는 모듈을 파싱한 뒤 변경되어서는 안 됩니다.
[[AsyncEvaluationOrder]] unset, an integer, or done 이 필드는 처음에 unset으로 설정되며 완전히 동기적인 모듈에서는 계속 unset입니다. 모듈 자체가 비동기이거나 비동기 종속성을 갖는 경우, 16.2.1.6.1.3.4이 대기 중인 모듈의 실행을 큐에 넣는 순서를 결정하는 정수로 설정됩니다. 대기 중인 모듈이 성공적으로 실행되면 이 필드는 done으로 설정됩니다.
[[TopLevelCapability]] a PromiseCapability Record or empty 이 모듈이 어떤 순환의 [[CycleRoot]]이고 해당 순환의 어떤 모듈에 대해 Evaluate()가 호출되었다면, 이 필드는 전체 평가에 대한 PromiseCapability Record를 포함합니다. Evaluate() 추상 메서드에서 반환한 Promise 객체를 settle하는 데 사용됩니다. 해당 모듈의 종속성에서는 일부 종속성에 대해 최상위 Evaluate()가 시작된 경우를 제외하면 이 필드가 empty입니다.
[[AsyncParentModules]] a List of Cyclic Module Records 이 모듈 또는 종속성의 [[HasTLA]]가 true이고 실행이 진행 중이면 최상위 실행 작업에 대해 이 모듈의 부모 importer를 추적합니다. 이러한 부모 모듈은 이 모듈이 성공적으로 실행을 완료하기 전에는 실행을 시작하지 않습니다.
[[PendingAsyncDependencies]] an integer or empty 이 모듈에 비동기 종속성이 있으면 이 모듈을 위해 아직 실행해야 하는 비동기 종속 모듈의 수를 추적합니다. 비동기 종속성이 있는 모듈은 이 필드가 0에 도달하고 실행 오류가 없을 때 실행됩니다.

표 40에 정의된 메서드 외에도 Cyclic Module Record에는 표 42에 나열된 추가 메서드가 있습니다:

표 42: Cyclic Module Record의 추가 추상 메서드
메서드 목적 정의
InitializeEnvironment ( )

추상 메서드 InitializeEnvironment. 인수 없음. 반환값: (정상 완료 (값: unused) 또는 throw 완료).

모든 가져온 바인딩을 해석하는 것을 포함하여 모듈의 Environment Record를 초기화하고 모듈의 실행 컨텍스트를 생성합니다.
이 명세에서는 다음 타입에 정의가 있으며, 호스트는 자체 정의를 갖는 추가 타입을 제공할 수 있습니다:
ExecuteModule ( [ capability ] )

추상 메서드 ExecuteModule. 선택적 인수 capability (PromiseCapability 레코드). 반환값: (정상 완료 (값: unused) 또는 throw 완료).

해당 실행 컨텍스트에서 모듈의 코드를 평가합니다. 이 모듈의 [[HasTLA]]가 true이면 PromiseCapability Record가 인수로 전달되며, 메서드는 주어진 capability를 resolve 또는 reject할 것으로 예상됩니다. 이 경우 메서드는 예외를 던져서는 안 되며 필요한 경우 대신 PromiseCapability Record를 reject해야 합니다.
이 명세에서는 다음 타입에 정의가 있으며, 호스트는 자체 정의를 갖는 추가 타입을 제공할 수 있습니다:

GraphLoadingState Record는 모듈 그래프의 로딩 과정에 관한 정보를 포함하는 Record입니다. HostLoadImportedModule 호출 이후 로딩을 계속하는 데 사용됩니다. 각 GraphLoadingState Record에는 표 43에 정의된 필드가 있습니다:

표 43: GraphLoadingState Record 필드
필드 이름 값 타입 의미
[[PromiseCapability]] a PromiseCapability Record 로딩 과정이 끝날 때 resolve할 promise입니다.
[[IsLoading]] a Boolean 로딩 과정이 성공이나 오류 어느 쪽으로도 아직 완료되지 않았으면 true입니다.
[[PendingModulesCount]] a non-negative integer 대기 중인 HostLoadImportedModule 호출 수를 추적합니다.
[[Visited]] a List of Cyclic Module Records 순환 종속성에 의한 무한 루프를 피하기 위해 현재 로딩 과정에서 이미 로드된 Cyclic Module Record의 목록입니다.
[[HostDefined]] anything (default value is empty) LoadRequestedModules 호출자에서 HostLoadImportedModule로 전달할 호스트 정의 데이터를 포함합니다.

16.2.1.6.1 Module Record 추상 메서드의 구현

다음은 표 40에 정의된 대응 Module Record 추상 메서드를 구현하는 Cyclic Module Record의 구체 메서드입니다.

16.2.1.6.1.1 LoadRequestedModules ( [ hostDefined ] )

a Cyclic Module Record module의 구체 메서드 LoadRequestedModules. 선택적 인수 hostDefined (임의의 값). 반환값: Promise. module의 종속성 그래프에 있는 모든 Module Record의 [[LoadedModules]]를 채웁니다(대부분의 작업은 보조 함수 InnerModuleLoading이 수행합니다). HostLoadImportedModule 훅에 전달되는 선택적 hostDefined 매개변수를 받습니다. 호출되면 다음 단계를 수행한다.

  1. hostDefined가 존재하지 않으면 hostDefined를 empty로 설정합니다.
  2. promiseCapability를 ! NewPromiseCapability(%Promise%)로 둡니다.
  3. state를 GraphLoadingState Record { [[IsLoading]]: true, [[PendingModulesCount]]: 1, [[Visited]]: « », [[PromiseCapability]]: promiseCapability, [[HostDefined]]: hostDefined }로 둡니다.
  4. InnerModuleLoading(state, module)을 수행합니다.
  5. promiseCapability.[[Promise]]를 반환합니다.
참고
hostDefined 매개변수는 가져온 모듈을 가져오는 데 필요한 추가 정보를 전달하는 데 사용할 수 있습니다. 예를 들어 HTML은 이를 사용하여 <link rel="preload" as="..."> 태그에 올바른 fetch destination을 설정합니다. import() 표현식은 hostDefined 매개변수를 절대로 설정하지 않습니다.

16.2.1.6.1.1.1 InnerModuleLoading ( state, module )

추상 연산 InnerModuleLoading. 인수 state (GraphLoadingState 레코드) 및 module (Module 레코드). 반환값: unused. LoadRequestedModules가 module의 종속성 그래프에 대한 실제 로딩 과정을 재귀적으로 수행하는 데 사용합니다. 호출되면 다음 단계를 수행한다.

  1. 단언: state.[[IsLoading]]은 true입니다.
  2. module이 Cyclic Module Record이고 module.[[Status]]가 new이며 state.[[Visited]]에 module이 포함되어 있지 않으면, 다음을 수행합니다.
    1. module을 state.[[Visited]]에 추가합니다.
    2. requestedModulesCount를 module.[[RequestedModules]]의 요소 수로 둡니다.
    3. state.[[PendingModulesCount]]를 state.[[PendingModulesCount]] + requestedModulesCount로 설정합니다.
    4. module.[[RequestedModules]]의 각 ModuleRequest Record request에 대해 다음을 수행합니다.
      1. AllImportAttributesSupported(request.[[Attributes]])가 false이면, 다음을 수행합니다.
        1. error를 ThrowCompletion(새로 생성된 SyntaxError 객체)으로 둡니다.
        2. ContinueModuleLoading(state, error)을 수행합니다.
      2. 그렇지 않고 module.[[LoadedModules]]에 ModuleRequestsEqual(record, request)이 true인 LoadedModuleRequest Record record가 포함되어 있으면, 다음을 수행합니다.
        1. InnerModuleLoading(state, record.[[Module]])을 수행합니다.
      3. 그렇지 않으면,
        1. HostLoadImportedModule(module, request, state.[[HostDefined]], state)을 수행합니다.
        2. 참고: HostLoadImportedModule은 FinishLoadingImportedModule을 호출하며, FinishLoadingImportedModule은 ContinueModuleLoading을 통해 그래프 로딩 과정에 다시 진입합니다.
      4. state.[[IsLoading]]이 false이면 unused를 반환합니다.
  3. 단언: state.[[PendingModulesCount]] ≥ 1입니다.
  4. state.[[PendingModulesCount]]를 state.[[PendingModulesCount]] - 1로 설정합니다.
  5. state.[[PendingModulesCount]] = 0이면, 다음을 수행합니다.
    1. state.[[IsLoading]]을 false로 설정합니다.
    2. state.[[Visited]]의 각 Cyclic Module Record loaded에 대해 다음을 수행합니다.
      1. loaded.[[Status]]가 new이면 loaded.[[Status]]를 unlinked로 설정합니다.
    3. ! Call(state.[[PromiseCapability]].[[Resolve]], undefined, « undefined »)를 수행합니다.
  6. unused를 반환합니다.

16.2.1.6.1.1.2 ContinueModuleLoading ( state, moduleCompletion )

추상 연산 ContinueModuleLoading. 인수 state (GraphLoadingState 레코드) 및 moduleCompletion ((정상 완료 (값: Module 레코드) 또는 throw 완료)). 반환값: unused. HostLoadImportedModule 호출 후 로딩 과정에 다시 진입하는 데 사용됩니다. 호출되면 다음 단계를 수행한다.

  1. state.[[IsLoading]]이 false이면 unused를 반환합니다.
  2. moduleCompletion이 정상 완료이면, 다음을 수행합니다.
    1. InnerModuleLoading(state, moduleCompletion.[[Value]])을 수행합니다.
  3. 그렇지 않으면,
    1. state.[[IsLoading]]을 false로 설정합니다.
    2. ! Call(state.[[PromiseCapability]].[[Reject]], undefined, « moduleCompletion.[[Value]] »)를 수행합니다.
  4. unused를 반환합니다.

16.2.1.6.1.2 Link ( )

a Cyclic Module Record module의 구체 메서드 Link. 인수 없음. 반환값: (정상 완료 (값: unused) 또는 throw 완료). 성공하면 Link는 이 모듈의 [[Status]]를 unlinked에서 linked로 전이합니다. 실패하면 예외가 던져지고 이 모듈의 [[Status]]는 unlinked 상태로 유지됩니다. (대부분의 작업은 보조 함수 InnerModuleLinking이 수행합니다.) 호출되면 다음 단계를 수행한다.

  1. 단언: module.[[Status]]는 unlinked, linked, evaluating-async 또는 evaluated 중 하나입니다.
  2. stack을 새로운 빈 List로 둡니다.
  3. result를 Completion(InnerModuleLinking(module, stack, 0))으로 둡니다.
  4. result가 비정상 완료이면, 다음을 수행합니다.
    1. stack의 각 Cyclic Module Record requiredModule에 대해 다음을 수행합니다.
      1. 단언: requiredModule.[[Status]]는 linking입니다.
      2. requiredModule.[[Status]]를 unlinked로 설정합니다.
    2. 단언: module.[[Status]]는 unlinked입니다.
    3. ? result를 반환합니다.
  5. 단언: module.[[Status]]는 linked, evaluating-async 또는 evaluated 중 하나입니다.
  6. 단언: stack은 비어 있습니다.
  7. unused를 반환합니다.

16.2.1.6.1.2.1 InnerModuleLinking ( module, stack, index )

추상 연산 InnerModuleLinking. 인수 module (Module 레코드), stack (리스트 (요소: Cyclic Module 레코드)) 및 index (음이 아닌 정수). 반환값: (정상 완료 (값: 음이 아닌 정수) 또는 throw 완료). Link가 module에 대한 실제 연결 과정을 수행하고 종속성 그래프의 다른 모든 모듈에도 재귀적으로 수행하는 데 사용합니다. stack과 index 매개변수 및 모듈의 [[DFSAncestorIndex]] 필드는 깊이 우선 탐색(DFS)을 추적합니다. 특히 [[DFSAncestorIndex]]는 강연결 요소(SCC)를 찾아내는 데 사용되며, 하나의 SCC에 있는 모든 모듈은 함께 linked로 전이합니다. 호출되면 다음 단계를 수행한다.

  1. module이 Cyclic Module Record가 아니면, 다음을 수행합니다.
    1. ? module.Link()를 수행합니다.
    2. index를 반환합니다.
  2. module.[[Status]]가 linking, linked, evaluating-async 또는 evaluated 중 하나이면, 다음을 수행합니다.
    1. index를 반환합니다.
  3. 단언: module.[[Status]]는 unlinked입니다.
  4. module.[[Status]]를 linking으로 설정합니다.
  5. moduleIndex를 index로 둡니다.
  6. module.[[DFSAncestorIndex]]를 index로 설정합니다.
  7. index를 index + 1로 설정합니다.
  8. module을 stack에 추가합니다.
  9. module.[[RequestedModules]]의 각 ModuleRequest Record request에 대해 다음을 수행합니다.
    1. requiredModule을 GetImportedModule(module, request)로 둡니다.
    2. index를 ? InnerModuleLinking(requiredModule, stack, index)으로 설정합니다.
    3. requiredModule이 Cyclic Module Record이면, 다음을 수행합니다.
      1. 단언: requiredModule.[[Status]]는 linking, linked, evaluating-async 또는 evaluated 중 하나입니다.
      2. 단언: requiredModule.[[Status]]가 linking인 것과 stack에 requiredModule이 포함되어 있는 것은 동치입니다.
      3. requiredModule.[[Status]]가 linking이면, 다음을 수행합니다.
        1. module.[[DFSAncestorIndex]]를 min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]])로 설정합니다.
  10. ? module.InitializeEnvironment()를 수행합니다.
  11. 단언: module은 stack에 정확히 한 번 나타납니다.
  12. 단언: module.[[DFSAncestorIndex]] ≤ moduleIndex입니다.
  13. module.[[DFSAncestorIndex]] = moduleIndex이면, 다음을 수행합니다.
    1. done을 false로 둡니다.
    2. done이 false인 동안 다음을 반복합니다.
      1. requiredModule을 stack의 마지막 요소로 둡니다.
      2. stack의 마지막 요소를 제거합니다.
      3. 단언: requiredModule은 Cyclic Module Record입니다.
      4. requiredModule.[[Status]]를 linked로 설정합니다.
      5. requiredModule과 module이 동일한 Module Record이면 done을 true로 설정합니다.
  14. index를 반환합니다.

16.2.1.6.1.3 Evaluate ( )

a Cyclic Module Record module의 구체 메서드 Evaluate. 인수 없음. 반환값: Promise. Evaluate는 이 모듈의 [[Status]]를 linked에서 evaluating-async 또는 evaluated로 전이합니다. 주어진 강연결 요소의 모듈에 대해 처음 호출될 때 Evaluate는 모듈 평가가 완료될 때 resolve되는 Promise를 생성하고 반환합니다. 이 Promise는 해당 요소의 [[CycleRoot]]의 [[TopLevelCapability]] 필드에 저장됩니다. 이후 해당 요소의 어떤 모듈에 대해 Evaluate를 호출해도 같은 Promise를 반환합니다. (대부분의 작업은 보조 함수 InnerModuleEvaluation이 수행합니다.) 호출되면 다음 단계를 수행한다.

  1. 단언: 이 Evaluate 호출은 주변 agent 안의 다른 Evaluate 호출과 동시에 발생하고 있지 않습니다.
  2. 단언: module.[[Status]]는 linked, evaluating-async 또는 evaluated 중 하나입니다.
  3. module.[[Status]]가 evaluating-async 또는 evaluated이면, 다음을 수행합니다.
    1. module.[[CycleRoot]]가 empty가 아니면, 다음을 수행합니다.
      1. module을 module.[[CycleRoot]]로 설정합니다.
    2. 그렇지 않으면,
      1. 단언: module.[[Status]]는 evaluated이고 module.[[EvaluationError]]는 throw 완료입니다.
  4. module.[[TopLevelCapability]]가 empty가 아니면, 다음을 수행합니다.
    1. module.[[TopLevelCapability]].[[Promise]]를 반환합니다.
  5. stack을 새로운 빈 List로 둡니다.
  6. promiseCapability을 ! NewPromiseCapability(%Promise%)로 둡니다.
  7. module.[[TopLevelCapability]]를 promiseCapability로 설정합니다.
  8. result를 Completion(InnerModuleEvaluation(module, stack, 0))으로 둡니다.
  9. result가 비정상 완료이면, 다음을 수행합니다.
    1. stack의 각 Cyclic Module Record requiredModule에 대해 다음을 수행합니다.
      1. 단언: requiredModule.[[Status]]는 evaluating입니다.
      2. requiredModule.[[Status]]를 evaluated로 설정합니다.
      3. requiredModule.[[EvaluationError]]를 result로 설정합니다.
    2. 단언: module.[[Status]]는 evaluated입니다.
    3. 단언: module.[[EvaluationError]]와 result는 동일한 Completion Record입니다.
    4. ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »)를 수행합니다.
  10. 그렇지 않으면,
    1. 단언: module.[[Status]]는 evaluating-async 또는 evaluated입니다.
    2. 단언: module.[[EvaluationError]]는 empty입니다.
    3. module.[[Status]]가 evaluated이면, 다음을 수행합니다.
      1. 단언: module.[[AsyncEvaluationOrder]]는 unset 또는 done입니다.
      2. 참고: module이 이미 평가되었고 해당 평가가 비동기였던 경우에만 module.[[AsyncEvaluationOrder]]는 done입니다.
      3. ! Call(promiseCapability.[[Resolve]], undefined, « undefined »)를 수행합니다.
    4. 단언: stack은 비어 있습니다.
  11. promiseCapability.[[Promise]]를 반환합니다.

16.2.1.6.1.3.1 InnerModuleEvaluation ( module, stack, index )

추상 연산 InnerModuleEvaluation. 인수 module (Module 레코드), stack (리스트 (요소: Cyclic Module 레코드)) 및 index (음이 아닌 정수). 반환값: (정상 완료 (값: 음이 아닌 정수) 또는 throw 완료). Evaluate가 module의 실제 평가 과정을 수행하고 종속성 그래프의 다른 모든 모듈에도 재귀적으로 수행하는 데 사용합니다. stack과 index 매개변수 및 module의 [[DFSAncestorIndex]] 필드는 InnerModuleLinking과 같은 방식으로 사용됩니다. 호출되면 다음 단계를 수행한다.

  1. module이 Cyclic Module Record가 아니면, 다음을 수행합니다.
    1. ? EvaluateModuleSync(module)를 수행합니다.
    2. index를 반환합니다.
  2. module.[[Status]]가 evaluating-async 또는 evaluated이면, 다음을 수행합니다.
    1. module.[[EvaluationError]]가 empty이면 index를 반환합니다.
    2. ? module.[[EvaluationError]]를 반환합니다.
  3. module.[[Status]]가 evaluating이면 index를 반환합니다.
  4. 단언: module.[[Status]]는 linked입니다.
  5. module.[[Status]]를 evaluating으로 설정합니다.
  6. moduleIndex를 index로 둡니다.
  7. module.[[DFSAncestorIndex]]를 index로 설정합니다.
  8. module.[[PendingAsyncDependencies]]를 0으로 설정합니다.
  9. index를 index + 1로 설정합니다.
  10. module을 stack에 추가합니다.
  11. module.[[RequestedModules]]의 각 ModuleRequest Record request에 대해 다음을 수행합니다.
    1. requiredModule을 GetImportedModule(module, request)로 둡니다.
    2. index를 ? InnerModuleEvaluation(requiredModule, stack, index)으로 설정합니다.
    3. requiredModule이 Cyclic Module Record이면, 다음을 수행합니다.
      1. 단언: requiredModule.[[Status]]는 evaluating, evaluating-async 또는 evaluated 중 하나입니다.
      2. 단언: requiredModule.[[Status]]가 evaluating인 것과 stack에 requiredModule이 포함되어 있는 것은 동치입니다.
      3. requiredModule.[[Status]]가 evaluating이면, 다음을 수행합니다.
        1. module.[[DFSAncestorIndex]]를 min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]])로 설정합니다.
      4. 그렇지 않으면,
        1. requiredModule을 requiredModule.[[CycleRoot]]로 설정합니다.
        2. 단언: requiredModule.[[Status]]는 evaluating-async 또는 evaluated입니다.
        3. requiredModule.[[EvaluationError]]가 empty가 아니면 ? requiredModule.[[EvaluationError]]를 반환합니다.
      5. requiredModule.[[AsyncEvaluationOrder]]가 정수이면, 다음을 수행합니다.
        1. module.[[PendingAsyncDependencies]]를 module.[[PendingAsyncDependencies]] + 1로 설정합니다.
        2. module을 requiredModule.[[AsyncParentModules]]에 추가합니다.
  12. module.[[HasTLA]]가 true이거나 module.[[PendingAsyncDependencies]] > 0이면, 다음을 수행합니다.
    1. 단언: module.[[AsyncEvaluationOrder]]는 unset입니다.
    2. module.[[AsyncEvaluationOrder]]를 IncrementModuleAsyncEvaluationCount()로 설정합니다.
    3. module.[[PendingAsyncDependencies]] = 0이면 ExecuteAsyncModule(module)을 수행합니다.
  13. 그렇지 않으면,
    1. ? module.ExecuteModule()를 수행합니다.
  14. 단언: module은 stack에 정확히 한 번 나타납니다.
  15. 단언: module.[[DFSAncestorIndex]] ≤ moduleIndex입니다.
  16. module.[[DFSAncestorIndex]] = moduleIndex이면, 다음을 수행합니다.
    1. done을 false로 둡니다.
    2. done이 false인 동안 다음을 반복합니다.
      1. requiredModule을 stack의 마지막 요소로 둡니다.
      2. stack의 마지막 요소를 제거합니다.
      3. 단언: requiredModule은 Cyclic Module Record입니다.
      4. 단언: requiredModule.[[AsyncEvaluationOrder]]는 정수 또는 unset입니다.
      5. requiredModule.[[AsyncEvaluationOrder]]가 unset이면 requiredModule.[[Status]]를 evaluated로 설정합니다.
      6. 그렇지 않으면 requiredModule.[[Status]]를 evaluating-async로 설정합니다.
      7. requiredModule과 module이 동일한 Module Record이면 done을 true로 설정합니다.
      8. requiredModule.[[CycleRoot]]를 module로 설정합니다.
  17. index를 반환합니다.
참고 1

모듈은 InnerModuleEvaluation이 순회하는 동안 evaluating입니다. 실행 완료 시에는 evaluated가 되며, [[HasTLA]] 필드가 true이거나 비동기 종속성이 있으면 실행 중에는 evaluating-async입니다.

참고 2

비동기 순환이 evaluating 상태가 아닐 때 그 순환의 모듈에 의존하는 모든 모듈은 대신 [[CycleRoot]]를 통해 순환 루트의 실행에 의존합니다. 이를 통해 순환 상태를 루트 모듈 상태를 통해 하나의 강연결 요소로 취급할 수 있습니다.

16.2.1.6.1.3.2 ExecuteAsyncModule ( module )

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

  1. 단언: module.[[Status]]는 evaluating 또는 evaluating-async입니다.
  2. 단언: module.[[HasTLA]]는 true입니다.
  3. promiseCapability을 ! NewPromiseCapability(%Promise%)로 둡니다.
  4. fulfilledClosure를 매개변수가 없고 module을 캡처하며 호출될 때 다음 단계를 수행하는 새로운 Abstract Closure로 둡니다:
    1. AsyncModuleExecutionFulfilled(module)을 수행합니다.
    2. NormalCompletion(undefined)을 반환합니다.
  5. onFulfilled를 CreateBuiltinFunction(fulfilledClosure, 0, "", « »)로 둡니다.
  6. rejectedClosure를 매개변수 (error)를 갖고 module을 캡처하며 호출될 때 다음 단계를 수행하는 새로운 Abstract Closure로 둡니다:
    1. AsyncModuleExecutionRejected(module, error)를 수행합니다.
    2. NormalCompletion(undefined)을 반환합니다.
  7. onRejected를 CreateBuiltinFunction(rejectedClosure, 0, "", « »)로 둡니다.
  8. PerformPromiseThen(promiseCapability.[[Promise]], onFulfilled, onRejected)을 수행합니다.
  9. ! module.ExecuteModule(promiseCapability)를 수행합니다.
  10. unused를 반환합니다.

16.2.1.6.1.3.3 GatherAvailableAncestors ( module, execList )

추상 연산 GatherAvailableAncestors. 인수 module (Cyclic Module 레코드) 및 execList (리스트 (요소: Cyclic Module 레코드)). 반환값: unused. 호출되면 다음 단계를 수행한다.

  1. module.[[AsyncParentModules]]의 각 Cyclic Module Record ancestorModule에 대해 다음을 수행합니다.
    1. execList에 ancestorModule이 포함되어 있지 않고 ancestorModule.[[CycleRoot]].[[EvaluationError]]가 empty이면, 다음을 수행합니다.
      1. 단언: ancestorModule.[[Status]]는 evaluating-async입니다.
      2. 단언: ancestorModule.[[EvaluationError]]는 empty입니다.
      3. 단언: ancestorModule.[[AsyncEvaluationOrder]]는 정수입니다.
      4. 단언: ancestorModule.[[PendingAsyncDependencies]] > 0입니다.
      5. ancestorModule.[[PendingAsyncDependencies]]를 ancestorModule.[[PendingAsyncDependencies]] - 1로 설정합니다.
      6. ancestorModule.[[PendingAsyncDependencies]] = 0이면, 다음을 수행합니다.
        1. ancestorModule을 execList에 추가합니다.
        2. ancestorModule.[[HasTLA]]가 false이면 GatherAvailableAncestors(ancestorModule, execList)을 수행합니다.
  2. unused를 반환합니다.
참고

루트 module의 비동기 실행이 이행되면 이 함수는 해당 완료에서 함께 동기적으로 실행할 수 있는 모듈 목록을 결정하여 execList에 채웁니다.

16.2.1.6.1.3.4 AsyncModuleExecutionFulfilled ( module )

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

  1. module.[[Status]]가 evaluated이면, 다음을 수행합니다.
    1. 단언: module.[[EvaluationError]]는 empty가 아닙니다.
    2. unused를 반환합니다.
  2. 단언: module.[[Status]]는 evaluating-async입니다.
  3. 단언: module.[[AsyncEvaluationOrder]]는 정수입니다.
  4. 단언: module.[[EvaluationError]]는 empty입니다.
  5. module.[[AsyncEvaluationOrder]]를 done으로 설정합니다.
  6. module.[[Status]]를 evaluated로 설정합니다.
  7. module.[[TopLevelCapability]]가 empty가 아니면, 다음을 수행합니다.
    1. 단언: module.[[CycleRoot]]와 module은 동일한 Module Record입니다.
    2. ! Call(module.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »)를 수행합니다.
  8. execList를 새로운 빈 List로 둡니다.
  9. GatherAvailableAncestors(module, execList)을 수행합니다.
  10. 단언: execList의 모든 요소는 [[AsyncEvaluationOrder]] 필드가 정수이고 [[PendingAsyncDependencies]] 필드가 0이며 [[EvaluationError]] 필드가 empty입니다.
  11. sortedExecList를 execList의 요소를 [[AsyncEvaluationOrder]] 필드에 따라 오름차순으로 정렬한 List로 둡니다.
  12. sortedExecList의 각 Cyclic Module Record ancestorModule에 대해 다음을 수행합니다.
    1. ancestorModule.[[Status]]가 evaluated이면, 다음을 수행합니다.
      1. 단언: ancestorModule.[[EvaluationError]]는 empty가 아닙니다.
    2. 그렇지 않고 ancestorModule.[[HasTLA]]가 true이면, 다음을 수행합니다.
      1. ExecuteAsyncModule(ancestorModule)을 수행합니다.
    3. 그렇지 않으면,
      1. result를 Completion(ancestorModule.ExecuteModule())으로 둡니다.
      2. result가 비정상 완료이면, 다음을 수행합니다.
        1. AsyncModuleExecutionRejected(ancestorModule, result.[[Value]])를 수행합니다.
      3. 그렇지 않으면,
        1. ancestorModule.[[AsyncEvaluationOrder]]를 done으로 설정합니다.
        2. ancestorModule.[[Status]]를 evaluated로 설정합니다.
        3. ancestorModule.[[TopLevelCapability]]가 empty가 아니면, 다음을 수행합니다.
          1. 단언: ancestorModule.[[CycleRoot]]와 ancestorModule은 동일한 Module Record입니다.
          2. ! Call(ancestorModule.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »)를 수행합니다.
  13. unused를 반환합니다.

16.2.1.6.1.3.5 AsyncModuleExecutionRejected ( module, error )

추상 연산 AsyncModuleExecutionRejected. 인수 module (Cyclic Module 레코드) 및 error (ECMAScript 언어 값). 반환값: unused. 호출되면 다음 단계를 수행한다.

  1. module.[[Status]]가 evaluated이면, 다음을 수행합니다.
    1. 단언: module.[[EvaluationError]]는 empty가 아닙니다.
    2. unused를 반환합니다.
  2. 단언: module.[[Status]]는 evaluating-async입니다.
  3. 단언: module.[[AsyncEvaluationOrder]]는 정수입니다.
  4. 단언: module.[[EvaluationError]]는 empty입니다.
  5. module.[[EvaluationError]]를 ThrowCompletion(error)로 설정합니다.
  6. module.[[Status]]를 evaluated로 설정합니다.
  7. module.[[AsyncEvaluationOrder]]를 done으로 설정합니다.
  8. 참고: module.[[AsyncEvaluationOrder]]는 AsyncModuleExecutionFulfilled와 대칭을 이루기 위해 done으로 설정됩니다. InnerModuleEvaluation에서는 모듈의 [[EvaluationError]] 내부 슬롯이 empty가 아니면 해당 모듈의 [[AsyncEvaluationOrder]] 내부 슬롯 값은 사용되지 않습니다.
  9. module.[[TopLevelCapability]]가 empty가 아니면, 다음을 수행합니다.
    1. 단언: module.[[CycleRoot]]와 module은 동일한 Module Record입니다.
    2. ! Call(module.[[TopLevelCapability]].[[Reject]], undefined, « error »)를 수행합니다.
  10. module.[[AsyncParentModules]]의 각 Cyclic Module Record ancestorModule에 대해 다음을 수행합니다.
    1. AsyncModuleExecutionRejected(ancestorModule, error)를 수행합니다.
  11. unused를 반환합니다.

16.2.1.6.2 Cyclic Module Record 그래프 예제

이 비규범적 절에서는 오류가 어떻게 발생할 수 있는지에 특히 초점을 맞추어 몇 가지 일반적인 모듈 그래프의 연결 및 평가 예를 제시합니다.

먼저 다음의 단순한 모듈 그래프를 살펴보겠습니다:

그림 2: 단순한 모듈 그래프
모듈 A가 모듈 B에 의존하고 모듈 B가 모듈 C에 의존하는 모듈 그래프

먼저 오류 조건이 없다고 가정하겠습니다. 호스트가 처음 A.LoadRequestedModules()를 호출하면 가정에 따라 성공적으로 완료되고 B와 C의 종속성(각각 C와 없음)도 재귀적으로 로드한 다음 A.[[Status]] = B.[[Status]] = C.[[Status]] = unlinked로 설정합니다. 그런 다음 호스트가 A.Link()를 호출하면 역시 가정에 따라 성공적으로 완료되어 A.[[Status]] = B.[[Status]] = C.[[Status]] = linked가 됩니다. 이러한 준비 단계는 언제든 수행할 수 있습니다. 이후 호스트가 모듈의 가능한 부작용을 발생시킬 준비가 되면 A.Evaluate()를 호출할 수 있으며, 이는 성공적으로 완료되어 undefined로 resolve되는 Promise를 반환하고(역시 가정에 따라) 먼저 C, 그다음 B를 재귀적으로 평가합니다. 이 시점에서 각 모듈의 [[Status]]는 evaluated입니다.

그다음 A.LoadRequestedModules()를 성공적으로 호출한 이후 연결 오류가 발생하는 경우를 살펴보겠습니다. C의 InnerModuleLinking은 성공하지만 그 이후 B에서 실패하는 경우, 예를 들어 B가 C가 제공하지 않는 항목을 가져오려고 하면 원래의 A.Link()는 실패하고 A와 B의 [[Status]]는 모두 unlinked로 남습니다. 그러나 C의 [[Status]]는 linked가 됩니다.

마지막으로 Link()를 성공적으로 호출한 뒤 평가 오류가 발생하는 경우를 살펴보겠습니다. C의 InnerModuleEvaluation은 성공하지만 그 이후 B에서 실패하는 경우, 예를 들어 B에 예외를 던지는 코드가 포함되어 있으면 원래의 A.Evaluate()는 실패하여 reject된 Promise를 반환합니다. 그 결과 예외는 A와 B의 [[EvaluationError]] 필드 모두에 기록되고 [[Status]]는 evaluated가 됩니다. C도 evaluated가 되지만 A와 B와 달리 평가를 성공적으로 완료했으므로 [[EvaluationError]]는 없는 상태로 유지됩니다. 예외를 저장함으로써 호스트가 Evaluate() 메서드를 호출하여 A 또는 B를 다시 사용하려 할 때마다 동일한 예외를 만나도록 보장합니다. (호스트는 Cyclic Module Record를 반드시 재사용해야 하는 것은 아니며, 마찬가지로 이러한 메서드가 던진 예외 객체를 노출해야 할 의무도 없습니다. 그러나 이 명세는 그러한 사용을 가능하게 합니다.)

이제 다른 종류의 오류 조건을 살펴보겠습니다:

그림 3: 해석할 수 없는 모듈이 있는 모듈 그래프
모듈 A가 누락된(해석할 수 없는) 모듈에 의존하며 해당 모듈을 ???로 나타낸 모듈 그래프

이 시나리오에서는 모듈 A가 다른 어떤 모듈에 대한 종속성을 선언하지만 해당 모듈에 대한 Module Record가 존재하지 않습니다. 즉, HostLoadImportedModule이 해당 모듈을 요청받았을 때 예외와 함께 FinishLoadingImportedModule을 호출합니다. 이는 대응 리소스가 존재하지 않거나 리소스는 존재하지만 결과 소스 텍스트를 파싱하려 할 때 ParseModule이 몇 가지 오류를 반환하는 등 여러 이유로 발생할 수 있습니다. 호스트는 FinishLoadingImportedModule에 전달하는 완료를 통해 실패 원인을 노출하도록 선택할 수 있습니다. 어떤 경우든 이 예외로 인해 로딩이 실패하며 A의 [[Status]]는 new 상태로 유지됩니다.

여기서 로딩, 연결 및 평가 오류가 서로 다른 이유는 다음 특성 때문입니다:

  • 평가는 부작용을 일으킬 수 있으므로 한 번만 수행해야 합니다. 따라서 실패했더라도 평가가 이미 수행되었는지 기억하는 것이 중요합니다. (오류의 경우 예외도 기억하는 것이 타당합니다. 그렇지 않으면 이후 Evaluate() 호출 때마다 새 예외를 합성해야 하기 때문입니다.)
  • 반면 연결에는 부작용이 없으므로 실패하더라도 나중에 문제없이 다시 시도할 수 있습니다.
  • 로딩은 호스트와 밀접하게 상호작용하며, 일부 호스트에서는 사용자가 실패한 로드를 다시 시도하도록 허용하는 것이 바람직할 수 있습니다(예: 일시적인 네트워크 상태 불량으로 실패한 경우).

이제 순환이 있는 모듈 그래프를 살펴보겠습니다:

그림 4: 순환 모듈 그래프
모듈 A가 모듈 B와 C에 의존하지만 모듈 B도 모듈 A에 의존하는 모듈 그래프

여기서는 진입점이 모듈 A라고 가정하므로 호스트는 A.LoadRequestedModules()를 호출하여 진행하며, 이는 A에 InnerModuleLoading을 수행합니다. 이어서 B와 C에 InnerModuleLoading을 호출합니다. 순환 때문에 A에 InnerModuleLoading이 다시 호출되지만, 이 시점에는 이 LoadRequestedModules 과정에서 A의 종속성 로딩이 이미 시작되었으므로 아무 작업도 하지 않습니다. 그래프의 모든 모듈이 성공적으로 로드되면 해당 [[Status]]는 동시에 new에서 unlinked로 전이합니다.

그다음 호스트는 A.Link()를 호출하며, 이는 A에 InnerModuleLinking을 수행합니다. 이어서 B에 InnerModuleLinking을 호출합니다. 순환 때문에 A에 InnerModuleLinking이 다시 호출되지만 이 시점에는 A.[[Status]]가 이미 linking이므로 아무 작업도 하지 않습니다. 제어가 A로 돌아오고 C에 InnerModuleLinking이 시작될 때 B.[[Status]] 자체는 계속 linking 상태입니다. 이 호출이 C.[[Status]]가 linked인 상태로 반환된 후 A와 B는 함께 linking에서 linked로 전이합니다. 이들이 하나의 강연결 요소를 형성하므로 이는 의도된 동작입니다. 이 단계에서 모듈 그래프는 깊이 우선 탐색으로 순회되므로 동일한 SCC에 있는 모듈의 상태를 동시에 전이할 수 있습니다.

성공하는 경우 순환 모듈 그래프의 평가 단계에서도 이와 유사한 과정이 발생합니다.

이제 A에 연결 오류가 있는 경우를 생각해 보겠습니다. 예를 들어 A가 C에 존재하지 않는 바인딩을 가져오려고 할 수 있습니다. 이 경우 A에 대한 두 번째 InnerModuleLinking 호출에서 조기 반환되는 것을 포함하여 위 단계는 여전히 발생합니다. 그러나 원래의 A에 대한 InnerModuleLinking으로 되돌아오면 InitializeEnvironment 중, 정확히는 C.ResolveExport() 직후에 실패합니다. 던져진 SyntaxError 예외는 A.Link까지 전파되며, A.Link는 현재 자신의 stack에 있는 모든 모듈(항상 아직 linking 상태인 모듈과 정확히 같습니다)을 재설정합니다. 따라서 A와 B는 모두 unlinked가 됩니다. C는 linked 상태로 남는다는 점에 유의하시기 바랍니다.

또는 A에 평가 오류가 있는 경우를 생각해 보겠습니다. 예를 들어 소스 코드가 예외를 던질 수 있습니다. 이 경우 A에 대한 두 번째 InnerModuleEvaluation 호출에서 조기 반환되는 것을 포함하여 위 단계에 대응하는 평가 시점의 과정이 여전히 발생합니다. 그러나 원래의 A에 대한 InnerModuleEvaluation으로 되돌아오면 가정대로 실패합니다. 던져진 예외는 A.Evaluate()까지 전파되며, A.Evaluate()는 현재 자신의 stack에 있는 모든 모듈(즉, 여전히 evaluating 상태인 모듈)과 [[AsyncParentModules]]를 통해 오류를 기록합니다. [[AsyncParentModules]]는 AsyncModuleExecutionRejected 알고리즘을 통해 전체 종속성 그래프에서 최상위 await를 포함하거나 이에 의존하는 모듈의 체인을 형성합니다. 따라서 A와 B는 모두 evaluated가 되고 예외는 A와 B의 [[EvaluationError]] 필드 모두에 기록되는 반면, C는 [[EvaluationError]] 없이 evaluated 상태로 남습니다.

마지막으로 모든 모듈이 비동기적으로 완료되는 순환 모듈 그래프를 살펴보겠습니다:

그림 5: 비동기 순환 모듈 그래프
모듈 A가 모듈 B와 C에 의존하고, 모듈 B는 모듈 D에 의존하며, 모듈 C는 모듈 D와 E에 의존하고, 모듈 D는 모듈 A에 의존하는 모듈 그래프

로딩과 연결은 이전과 동일하게 진행되며 모든 모듈은 [[Status]]가 linked로 설정된 상태가 됩니다.

A.Evaluate()를 호출하면 A, B, D에 InnerModuleEvaluation이 호출되고 이들은 모두 evaluating으로 전이합니다. 그런 다음 A에 InnerModuleEvaluation이 다시 호출되지만 이미 evaluating 상태이므로 아무 작업도 하지 않습니다. 이 시점에서 D.[[PendingAsyncDependencies]]는 0이므로 ExecuteAsyncModule(D)이 호출되고 D의 비동기 실행을 추적하는 새로운 PromiseCapability과 함께 D.ExecuteModule을 호출합니다. B에 대한 InnerModuleEvaluation으로 되돌아가면서 B.[[PendingAsyncDependencies]]를 1로, B.[[AsyncEvaluationOrder]]를 1로 설정합니다. 원래의 A에 대한 InnerModuleEvaluation으로 되돌아가면서 A.[[PendingAsyncDependencies]]를 1로 설정합니다. A의 종속성을 순회하는 다음 반복에서 C에 InnerModuleEvaluation을 호출하고, 따라서 D(다시 아무 작업도 하지 않음)와 E에도 호출합니다. E는 종속성이 없고 순환의 일부도 아니므로 D와 같은 방식으로 ExecuteAsyncModule(E)을 호출하고 E는 즉시 스택에서 제거됩니다. 다시 C에 대한 InnerModuleEvaluation으로 되돌아가 C.[[AsyncEvaluationOrder]]를 3으로 설정합니다. 이제 A의 종속성 순회를 끝내고 A.[[AsyncEvaluationOrder]]를 4로 설정한 다음 전체 강연결 요소를 스택에서 제거하여 모든 모듈을 한꺼번에 evaluating-async로 전이합니다. 이 시점의 모듈 필드는 표 44과 같습니다.

표 44: 초기 Evaluate() 호출 후의 모듈 필드
필드
모듈
A B C D E
[[DFSAncestorIndex]] 0 0 0 0 4
[[Status]] evaluating-async evaluating-async evaluating-async evaluating-async evaluating-async
[[AsyncEvaluationOrder]] 4 1 3 0 2
[[AsyncParentModules]] « » « A » « A » « B, C » « C »
[[PendingAsyncDependencies]] 2 (B and C) 1 (D) 2 (D and E) 0 0

E가 먼저 실행을 끝낸다고 가정하겠습니다. 이때 AsyncModuleExecutionFulfilled가 호출되고 E.[[Status]]는 evaluated로 설정되며 C.[[PendingAsyncDependencies]]는 1로 감소합니다. 갱신된 모듈 필드는 표 45와 같습니다.

표 45: 모듈 E의 실행이 끝난 후의 모듈 필드
필드
모듈
C E
[[DFSAncestorIndex]] 0 4
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 3 done
[[AsyncParentModules]] « A » « C »
[[PendingAsyncDependencies]] 1 (D) 0

다음으로 D가 실행을 끝냅니다(여전히 실행 중인 유일한 모듈이었습니다). 이때 AsyncModuleExecutionFulfilled가 다시 호출되고 D.[[Status]]는 evaluated로 설정됩니다. 실행할 수 있는 조상은 B([[AsyncEvaluationOrder]]가 1)와 C([[AsyncEvaluationOrder]]가 3)이므로 B가 먼저 처리됩니다. B.[[PendingAsyncDependencies]]는 0으로 감소하고 ExecuteAsyncModule이 B에 호출되어 실행을 시작합니다. C.[[PendingAsyncDependencies]]도 0으로 감소하고 C도 실행을 시작합니다(B에 await가 포함되어 있다면 B와 병렬로 실행될 수 있습니다). 갱신된 모듈 필드는 표 46과 같습니다.

표 46: 모듈 D의 실행이 끝난 후의 모듈 필드
필드
모듈
B C D
[[DFSAncestorIndex]] 0 0 0
[[Status]] evaluating-async evaluating-async evaluated
[[AsyncEvaluationOrder]] 1 3 done
[[AsyncParentModules]] « A » « A » « B, C »
[[PendingAsyncDependencies]] 0 0 0

다음으로 C가 실행을 끝낸다고 가정하겠습니다. 이때 AsyncModuleExecutionFulfilled가 다시 호출되고 C.[[Status]]는 evaluated로 설정되며 A.[[PendingAsyncDependencies]]는 1로 감소합니다. 갱신된 모듈 필드는 표 47와 같습니다.

표 47: 모듈 C의 실행이 끝난 후의 모듈 필드
필드
모듈
A C
[[DFSAncestorIndex]] 0 0
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 4 done
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 1 (B) 0

그다음 B가 실행을 끝냅니다. 이때 AsyncModuleExecutionFulfilled가 다시 호출되고 B.[[Status]]는 evaluated로 설정됩니다. A.[[PendingAsyncDependencies]]는 0으로 감소하므로 ExecuteAsyncModule이 호출되어 실행을 시작합니다. 갱신된 모듈 필드는 표 48와 같습니다.

표 48: 모듈 B의 실행이 끝난 후의 모듈 필드
필드
모듈
A B
[[DFSAncestorIndex]] 0 0
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 4 done
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 0 0

마지막으로 A가 실행을 끝냅니다. 이때 AsyncModuleExecutionFulfilled가 다시 호출되고 A.[[Status]]는 evaluated로 설정됩니다. 이 시점에서 A.[[TopLevelCapability]]의 Promise(A.Evaluate()가 반환했던 Promise)가 resolve되며 이 모듈 그래프의 처리가 끝납니다. 갱신된 모듈 필드는 표 49과 같습니다.

표 49: 모듈 A의 실행이 끝난 후의 모듈 필드
필드
모듈
A
[[DFSAncestorIndex]] 0
[[Status]] evaluated
[[AsyncEvaluationOrder]] done
[[AsyncParentModules]] « »
[[PendingAsyncDependencies]] 0

또는 B가 실행을 끝내기 전에 C의 실행이 실패하여 오류를 반환하는 실패 사례를 생각해 보겠습니다. 이때 AsyncModuleExecutionRejected가 호출되고 C.[[Status]]는 evaluated로, C.[[EvaluationError]]는 해당 오류로 설정됩니다. 그런 다음 각 AsyncParentModules에 AsyncModuleExecutionRejected를 수행하여 이 오류를 모든 AsyncParentModules에 전파합니다. 갱신된 모듈 필드는 표 50과 같습니다.

표 50: 모듈 C가 오류와 함께 완료된 후의 모듈 필드
필드
모듈
A C
[[DFSAncestorIndex]] 0 0
[[Status]] evaluated evaluated
[[AsyncEvaluationOrder]] done done
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 1 (B) 0
[[EvaluationError]] empty C's evaluation error

C가 C의 오류를 사용하여 A에 AsyncModuleExecutionRejected를 호출하므로 A는 C와 동일한 오류로 reject됩니다. A.[[Status]]는 evaluated로 설정됩니다. 이 시점에서 A.[[TopLevelCapability]]의 Promise(A.Evaluate()가 반환했던 Promise)는 reject됩니다. 갱신된 모듈 필드는 표 51과 같습니다.

표 51: 모듈 A가 reject된 후의 모듈 필드
필드
모듈
A
[[DFSAncestorIndex]] 0
[[Status]] evaluated
[[AsyncEvaluationOrder]] done
[[AsyncParentModules]] « »
[[PendingAsyncDependencies]] 0
[[EvaluationError]] C's Evaluation Error

그다음 B가 오류 없이 실행을 끝냅니다. 이때 AsyncModuleExecutionFulfilled가 다시 호출되고 B.[[Status]]는 evaluated로 설정됩니다. B에 GatherAvailableAncestors가 호출됩니다. 그러나 A.[[CycleRoot]]는 A이며 평가 오류를 갖고 있으므로 반환되는 sortedExecList에는 추가되지 않고 AsyncModuleExecutionFulfilled는 추가 처리 없이 반환합니다. 이후 B를 가져오는 모든 importer는 순환 루트 A에 설정된 C의 평가 오류에서 B.[[CycleRoot]].[[EvaluationError]]의 rejection을 해석합니다. 갱신된 모듈 필드는 표 52와 같습니다.

표 52: 오류가 발생하는 그래프에서 모듈 B의 실행이 끝난 후의 모듈 필드
필드
모듈
A B
[[DFSAncestorIndex]] 0 0
[[Status]] evaluated evaluated
[[AsyncEvaluationOrder]] 4 1
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 0 0
[[EvaluationError]] C's Evaluation Error empty

16.2.1.7 Source Text Module Record

Source Text Module Record는 목표 기호 Module을 사용하여 파싱한 ECMAScript 소스 텍스트(11)로 정의된 모듈에 관한 정보를 나타내는 데 사용됩니다. 그 필드에는 모듈이 가져오고 내보내는 이름에 관한 요약 정보가 포함되며, 구체 메서드는 이러한 요약 정보를 사용하여 모듈을 연결하고 평가합니다.

Source Text Module Record는 추상 Module Record 타입의 다른 하위 클래스와 함께 모듈 그래프에 존재할 수 있으며 Cyclic Module Record 타입의 다른 하위 클래스와 순환에 참여할 수 있습니다.

표 41에 정의된 필드 외에도 Source Text Module Record에는 표 53에 나열된 추가 필드가 있습니다. 이러한 각 필드는 처음 ParseModule에서 설정됩니다.

표 53: Source Text Module Record의 추가 필드
필드 이름 값 타입 의미
[[ECMAScriptCode]] a Parse Node Module을 목표 기호로 사용하여 이 모듈의 소스 텍스트를 파싱한 결과입니다.
[[Context]] an ECMAScript code execution context or empty 이 모듈과 연결된 실행 컨텍스트입니다. 모듈의 환경이 초기화될 때까지 empty입니다.
[[ImportMeta]] an Object or empty import.meta 메타 프로퍼티를 통해 노출되는 객체입니다. ECMAScript 코드가 접근할 때까지 empty입니다.
[[ImportEntries]] a List of ImportEntry Records 이 모듈의 코드에서 파생된 ImportEntry Record의 List입니다.
[[LocalExportEntries]] a List of ExportEntry Records 이 모듈 안에서 발생하는 선언에 대응하는, 이 모듈의 코드에서 파생된 ExportEntry Record의 List입니다.
[[IndirectExportEntries]] a List of ExportEntry Records 이 모듈 안에서 다시 내보내는 import 또는 export * as namespace 선언의 export에 대응하는, 이 모듈의 코드에서 파생된 ExportEntry Record의 List입니다.
[[StarExportEntries]] a List of ExportEntry Records 이 모듈 안의 export * 선언에 대응하는, 이 모듈의 코드에서 파생된 ExportEntry Record의 List입니다. export * as namespace 선언은 포함하지 않습니다.

ImportEntry Record는 하나의 선언적 import에 관한 정보를 요약하는 Record입니다. 각 ImportEntry Record에는 표 54에 정의된 필드가 있습니다:

표 54: ImportEntry Record 필드
필드 이름 값 타입 의미
[[ModuleRequest]] a ModuleRequest Record ImportDeclaration의 ModuleSpecifier 및 import 속성을 나타내는 ModuleRequest Record입니다.
[[ImportName]] a String or namespace [[ModuleRequest]]가 식별하는 모듈에서 원하는 바인딩이 내보내지는 이름입니다. 값 namespace는 import 요청이 대상 모듈의 네임스페이스 객체에 대한 것임을 나타냅니다.
[[LocalName]] a String 가져오는 모듈 안에서 가져온 값에 로컬로 접근하는 데 사용하는 이름입니다.
참고 1

표 55는 구문적 import 형식을 나타내는 데 사용되는 ImportEntry Record 필드의 예를 제공합니다:

표 55 (참고): Import 형식과 ImportEntry Record의 대응
Import 문 형식 [[ModuleRequest]] [[ImportName]] [[LocalName]]
import v from "mod"; "mod" "default" "v"
import * as ns from "mod"; "mod" namespace "ns"
import {x} from "mod"; "mod" "x" "x"
import {x as v} from "mod"; "mod" "x" "v"
import "mod"; ImportEntry Record는 생성되지 않습니다.

ExportEntry Record는 하나의 선언적 export에 관한 정보를 요약하는 Record입니다. 각 ExportEntry Record에는 표 56에 정의된 필드가 있습니다:

표 56: ExportEntry Record 필드
필드 이름 값 타입 의미
[[ExportName]] a String or null 이 모듈이 이 바인딩을 내보내는 데 사용하는 이름입니다.
[[ModuleRequest]] a ModuleRequest Record or null ExportDeclaration의 ModuleSpecifier 및 import 속성을 나타내는 ModuleRequest Record입니다. ExportDeclaration에 ModuleSpecifier가 없으면 null입니다.
[[ImportName]] a String, null, namespace, or all-but-default [[ModuleRequest]]가 식별하는 모듈에서 원하는 바인딩이 내보내지는 이름입니다. ExportDeclaration에 ModuleSpecifier가 없으면 null입니다. namespace는 export * as ns from "mod" 선언에 사용됩니다. all-but-default는 export * from "mod" 선언에 사용됩니다.
[[LocalName]] a String or null 모듈 안에서 내보낸 값에 로컬로 접근하는 데 사용하는 이름입니다. 모듈 안에서 내보낸 값에 로컬로 접근할 수 없으면 null입니다.
참고 2

표 57는 구문적 export 형식을 나타내는 데 사용되는 ExportEntry Record 필드의 예를 제공합니다:

표 57 (참고): Export 형식과 ExportEntry Record의 대응
Export 문 형식 [[ExportName]] [[ModuleRequest]] [[ImportName]] [[LocalName]]
export var v; "v" null null "v"
export default function f() {} "default" null null "f"
export default function () {} "default" null null "*default*"
export default 42; "default" null null "*default*"
export {x}; "x" null null "x"
export {v as x}; "x" null null "v"
export {x} from "mod"; "x" "mod" "x" null
export {v as x} from "mod"; "x" "mod" "v" null
export * from "mod"; null "mod" all-but-default null
export * as ns from "mod"; "ns" "mod" namespace null

다음 정의는 Source Text Module Record에 필요한 구체 메서드와 그 밖의 추상 연산을 명시합니다.

16.2.1.7.1 ParseModule ( sourceText, realm, hostDefined )

추상 연산 ParseModule. 인수 sourceText ((String 또는 a sequence of Unicode code points)), realm (Realm 레코드) 및 hostDefined (임의의 값). 반환값: (Source Text Module 레코드 또는 a non-empty List of SyntaxError objects). sourceText를 Module로 파싱한 결과를 기반으로 Source Text Module Record를 생성합니다. 호출되면 다음 단계를 수행한다.

  1. body를 ParseText(sourceText, Module)로 둡니다.
  2. body가 오류의 List이면 body를 반환합니다.
  3. requestedModules를 body의 ModuleRequests로 둡니다.
  4. importEntries를 body의 ImportEntries로 둡니다.
  5. importedBoundNames를 ImportedLocalNames(importEntries)로 둡니다.
  6. indirectExportEntries를 새로운 빈 List로 둡니다.
  7. localExportEntries를 새로운 빈 List로 둡니다.
  8. starExportEntries를 새로운 빈 List로 둡니다.
  9. exportEntries를 body의 ExportEntries로 둡니다.
  10. exportEntries의 각 ExportEntry Record exportEntry에 대해 다음을 수행합니다.
    1. exportEntry.[[ModuleRequest]]가 null이면, 다음을 수행합니다.
      1. importedBoundNames에 exportEntry.[[LocalName]]이 포함되어 있지 않으면, 다음을 수행합니다.
        1. exportEntry를 localExportEntries에 추가합니다.
      2. 그렇지 않으면,
        1. 참고: 원래 다른 모듈에서 가져온 바인딩 또는 네임스페이스 객체를 내보낼 때 ExportEntry Record는 바인딩 또는 네임스페이스 객체를 가져온 뒤 내보낸 것이 아니라 원래 모듈에서 직접 다시 내보냈다면 갖게 되었을 형식과 일치하도록 다시 작성됩니다. 이를 통해 export * from을 통해 동일한 이름으로 같은 바인딩 또는 네임스페이스를 두 번 내보내 발생하는 충돌을 Source Text Module Record의 ResolveExport 구체 메서드의 9.e.iii 단계에서 모호한 것으로 취급하지 않고 무시할 수 있습니다.
        2. importEntry를 [[LocalName]]이 exportEntry.[[LocalName]]인 importEntries의 요소로 둡니다.
        3. ExportEntry Record { [[ModuleRequest]]: importEntry.[[ModuleRequest]], [[ImportName]]: importEntry.[[ImportName]], [[LocalName]]: null, [[ExportName]]: exportEntry.[[ExportName]] }를 indirectExportEntries에 추가합니다.
    2. 그렇지 않고 exportEntry.[[ImportName]]이 all-but-default이면, 다음을 수행합니다.
      1. 단언: exportEntry.[[ExportName]]은 null입니다.
      2. exportEntry를 starExportEntries에 추가합니다.
    3. 그렇지 않으면,
      1. exportEntry를 indirectExportEntries에 추가합니다.
  11. async를 body Contains await로 둡니다.
  12. Source Text Module Record { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[CycleRoot]]: empty, [[HasTLA]]: async, [[AsyncEvaluationOrder]]: unset, [[TopLevelCapability]]: empty, [[AsyncParentModules]]: « », [[PendingAsyncDependencies]]: empty, [[Status]]: new, [[EvaluationError]]: empty, [[HostDefined]]: hostDefined, [[ECMAScriptCode]]: body, [[Context]]: empty, [[ImportMeta]]: empty, [[RequestedModules]]: requestedModules, [[LoadedModules]]: « », [[ImportEntries]]: importEntries, [[LocalExportEntries]]: localExportEntries, [[IndirectExportEntries]]: indirectExportEntries, [[StarExportEntries]]: starExportEntries, [[DFSAncestorIndex]]: empty }를 반환합니다.
참고

구현체는 해당 모듈 소스 텍스트에 ParseModule을 평가하기 전에 모듈 소스 텍스트를 파싱하고 조기 오류 조건을 분석할 수 있습니다. 그러나 오류 보고는 이 명세가 실제로 해당 소스 텍스트에 ParseModule을 수행하는 시점까지 지연되어야 합니다.

16.2.1.7.2 Module Record 추상 메서드의 구현

다음은 표 40에 정의된 대응 Module Record 추상 메서드를 구현하는 Source Text Module Record의 구체 메서드입니다.

16.2.1.7.2.1 GetExportedNames ( [ exportStarSet ] )

a Source Text Module Record module의 구체 메서드 GetExportedNames. 선택적 인수 exportStarSet (리스트 (요소: Source Text Module 레코드)). 반환값: 리스트 (요소: String). 호출되면 다음 단계를 수행한다.

  1. 단언: module.[[Status]]는 new가 아닙니다.
  2. exportStarSet이 존재하지 않으면 exportStarSet을 새로운 빈 List로 설정합니다.
  3. exportStarSet에 module이 포함되어 있으면, 다음을 수행합니다.
    1. 단언: export * 순환의 시작점에 도달했습니다.
    2. 새로운 빈 List를 반환합니다.
  4. module을 exportStarSet에 추가합니다.
  5. exportedNames를 새로운 빈 List로 둡니다.
  6. module.[[LocalExportEntries]]의 각 ExportEntry Record exportEntry에 대해 다음을 수행합니다.
    1. 단언: module은 이 export에 대한 직접 바인딩을 제공합니다.
    2. 단언: exportEntry.[[ExportName]]은 null이 아닙니다.
    3. exportEntry.[[ExportName]]을 exportedNames에 추가합니다.
  7. module.[[IndirectExportEntries]]의 각 ExportEntry Record exportEntry에 대해 다음을 수행합니다.
    1. 단언: module은 이 export를 위해 특정 바인딩을 가져옵니다.
    2. 단언: exportEntry.[[ExportName]]은 null이 아닙니다.
    3. exportEntry.[[ExportName]]을 exportedNames에 추가합니다.
  8. module.[[StarExportEntries]]의 각 ExportEntry Record exportEntry에 대해 다음을 수행합니다.
    1. 단언: exportEntry.[[ModuleRequest]]는 null이 아닙니다.
    2. requestedModule을 GetImportedModule(module, exportEntry.[[ModuleRequest]])로 둡니다.
    3. starNames를 requestedModule.GetExportedNames(exportStarSet)로 둡니다.
    4. starNames의 각 요소 name에 대해 다음을 수행합니다.
      1. name이 "default"가 아니면, 다음을 수행합니다.
        1. exportedNames에 name이 포함되어 있지 않으면, 다음을 수행합니다.
          1. name을 exportedNames에 추가합니다.
  9. exportedNames를 반환합니다.
참고

GetExportedNames는 모호한 star export 바인딩을 가진 이름을 걸러내거나 이에 대해 예외를 던지지 않습니다.

16.2.1.7.2.2 ResolveExport ( exportName [ , resolveSet ] )

a Source Text Module Record module의 구체 메서드 ResolveExport. 인수 exportName (String) 및 선택적 인수 resolveSet (리스트 (요소: 레코드 (필드: [[Module]] (Module 레코드), [[ExportName]] (String)))). 반환값: (ResolvedBinding 레코드, null 또는 ambiguous).

ResolveExport는 가져온 바인딩을 실제 정의 모듈 및 로컬 바인딩 이름으로 해석하려고 합니다. 정의 모듈은 이 메서드를 호출한 Module Record가 나타내는 모듈일 수도 있고, 해당 모듈이 가져오는 다른 모듈일 수도 있습니다. 매개변수 resolveSet은 해석되지 않은 순환 import/export 경로를 검출하는 데 사용됩니다. 이미 resolveSet에 있는 특정 Module Record와 exportName으로 구성된 쌍에 도달하면 import 순환이 발생한 것입니다. ResolveExport를 재귀적으로 호출하기 전에 module과 exportName으로 구성된 쌍을 resolveSet에 추가합니다.

정의 모듈을 찾으면 ResolvedBinding Record { [[Module]], [[BindingName]] }을 반환합니다. 이 Record는 로컬 바인딩이 없는 네임스페이스 export인 경우를 제외하고 원래 요청한 export의 해석된 바인딩을 식별합니다. 이 경우 [[BindingName]]은 namespace로 설정됩니다. 정의를 찾지 못했거나 요청이 순환인 것으로 확인되면 null을 반환합니다. 요청이 모호한 것으로 확인되면 ambiguous를 반환합니다.

호출되면 다음 단계를 수행한다.

  1. 단언: module.[[Status]]는 new가 아닙니다.
  2. resolveSet이 존재하지 않으면 resolveSet을 새로운 빈 List로 설정합니다.
  3. resolveSet의 각 Record { [[Module]], [[ExportName]] } record에 대해 다음을 수행합니다.
    1. module과 record.[[Module]]이 동일한 Module Record이고 exportName이 record.[[ExportName]]과 같으면, 다음을 수행합니다.
      1. 단언: 이는 순환 import 요청입니다.
      2. null을 반환합니다.
  4. Record { [[Module]]: module, [[ExportName]]: exportName }을 resolveSet에 추가합니다.
  5. module.[[LocalExportEntries]]의 각 ExportEntry Record exportEntry에 대해 다음을 수행합니다.
    1. exportEntry.[[ExportName]]이 exportName과 같으면, 다음을 수행합니다.
      1. 단언: module은 이 export에 대한 직접 바인딩을 제공합니다.
      2. ResolvedBinding Record { [[Module]]: module, [[BindingName]]: exportEntry.[[LocalName]] }을 반환합니다.
  6. module.[[IndirectExportEntries]]의 각 ExportEntry Record exportEntry에 대해 다음을 수행합니다.
    1. exportEntry.[[ExportName]]이 exportName과 같으면, 다음을 수행합니다.
      1. 단언: exportEntry.[[ModuleRequest]]는 null이 아닙니다.
      2. importedModule을 GetImportedModule(module, exportEntry.[[ModuleRequest]])로 둡니다.
      3. exportEntry.[[ImportName]]이 namespace이면, 다음을 수행합니다.
        1. 단언: module은 이 export에 대한 직접 바인딩을 제공하지 않습니다.
        2. ResolvedBinding Record { [[Module]]: importedModule, [[BindingName]]: namespace }을 반환합니다.
      4. 단언: module은 이 export를 위해 특정 바인딩을 가져옵니다.
      5. 단언: exportEntry.[[ImportName]]은 String입니다.
      6. importedModule.ResolveExport(exportEntry.[[ImportName]], resolveSet)를 반환합니다.
  7. exportName이 "default"이면, 다음을 수행합니다.
    1. 단언: 이 모듈은 default export를 명시적으로 정의하지 않았습니다.
    2. null을 반환합니다.
    3. 참고: default export는 export * from "mod" 선언에서 제공할 수 없습니다.
  8. starResolution을 null로 둡니다.
  9. module.[[StarExportEntries]]의 각 ExportEntry Record exportEntry에 대해 다음을 수행합니다.
    1. 단언: exportEntry.[[ModuleRequest]]는 null이 아닙니다.
    2. importedModule을 GetImportedModule(module, exportEntry.[[ModuleRequest]])로 둡니다.
    3. resolution을 importedModule.ResolveExport(exportName, resolveSet)로 둡니다.
    4. resolution이 ambiguous이면 ambiguous를 반환합니다.
    5. resolution이 null이 아니면, 다음을 수행합니다.
      1. 단언: resolution은 ResolvedBinding Record입니다.
      2. starResolution이 null이면, 다음을 수행합니다.
        1. starResolution을 resolution으로 설정합니다.
      3. 그렇지 않으면,
        1. 단언: 요청한 이름을 포함하는 * export가 둘 이상 있습니다.
        2. resolution.[[Module]]과 starResolution.[[Module]]이 동일한 Module Record가 아니면 ambiguous를 반환합니다.
        3. resolution.[[BindingName]]이 starResolution.[[BindingName]]과 같지 않으면 ambiguous를 반환합니다.
  10. starResolution을 반환합니다.

16.2.1.7.3 Cyclic Module Record 추상 메서드의 구현

다음은 표 42에 정의된 대응 Cyclic Module Record 추상 메서드를 구현하는 Source Text Module Record의 구체 메서드입니다.

16.2.1.7.3.1 InitializeEnvironment ( )

a Source Text Module Record module의 구체 메서드 InitializeEnvironment. 인수 없음. 반환값: (정상 완료 (값: unused) 또는 throw 완료). 호출되면 다음 단계를 수행한다.

  1. module.[[IndirectExportEntries]]의 각 ExportEntry Record exportEntry에 대해 다음을 수행합니다.
    1. 단언: exportEntry.[[ExportName]]은 null이 아닙니다.
    2. resolution을 module.ResolveExport(exportEntry.[[ExportName]])로 둡니다.
    3. resolution이 null 또는 ambiguous 중 하나이면 SyntaxError 예외를 던집니다.
    4. 단언: resolution은 ResolvedBinding Record입니다.
  2. 단언: module의 모든 이름 있는 export는 해석 가능합니다.
  3. realm을 module.[[Realm]]으로 둡니다.
  4. 단언: realm은 undefined가 아닙니다.
  5. envRecord를 NewModuleEnvironment(realm.[[GlobalEnv]])로 둡니다.
  6. module.[[Environment]]를 envRecord로 설정합니다.
  7. module.[[ImportEntries]]의 각 ImportEntry Record importEntry에 대해 다음을 수행합니다.
    1. importedModule을 GetImportedModule(module, importEntry.[[ModuleRequest]])로 둡니다.
    2. importEntry.[[ImportName]]이 namespace이면, 다음을 수행합니다.
      1. namespace를 GetModuleNamespace(importedModule)로 둡니다.
      2. ! envRecord.CreateImmutableBinding(importEntry.[[LocalName]], true)를 수행합니다.
      3. ! envRecord.InitializeBinding(importEntry.[[LocalName]], namespace)를 수행합니다.
    3. 그렇지 않으면,
      1. 단언: importEntry.[[ImportName]]은 String입니다.
      2. resolution을 importedModule.ResolveExport(importEntry.[[ImportName]])로 둡니다.
      3. resolution이 null 또는 ambiguous 중 하나이면 SyntaxError 예외를 던집니다.
      4. resolution.[[BindingName]]이 namespace이면, 다음을 수행합니다.
        1. namespace를 GetModuleNamespace(resolution.[[Module]])로 둡니다.
        2. ! envRecord.CreateImmutableBinding(importEntry.[[LocalName]], true)를 수행합니다.
        3. ! envRecord.InitializeBinding(importEntry.[[LocalName]], namespace)를 수행합니다.
      5. 그렇지 않으면,
        1. CreateImportBinding(envRecord, importEntry.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]])을 수행합니다.
  8. moduleContext를 새로운 ECMAScript 코드 실행 컨텍스트로 둡니다.
  9. moduleContext의 Function을 null로 설정합니다.
  10. 단언: module.[[Realm]]은 undefined가 아닙니다.
  11. moduleContext의 Realm을 module.[[Realm]]으로 설정합니다.
  12. moduleContext의 ScriptOrModule을 module로 설정합니다.
  13. moduleContext의 VariableEnvironment를 module.[[Environment]]로 설정합니다.
  14. moduleContext의 LexicalEnvironment를 module.[[Environment]]로 설정합니다.
  15. moduleContext의 PrivateEnvironment를 null로 설정합니다.
  16. module.[[Context]]를 moduleContext로 설정합니다.
  17. moduleContext를 실행 컨텍스트 스택에 푸시합니다. 이제 moduleContext가 실행 중인 실행 컨텍스트입니다.
  18. code를 module.[[ECMAScriptCode]]로 둡니다.
  19. variableDecls를 code의 VarScopedDeclarations로 둡니다.
  20. declaredVariableNames를 새로운 빈 List로 둡니다.
  21. variableDecls의 각 요소 variableDecl에 대해 다음을 수행합니다.
    1. variableDecl의 BoundNames의 각 요소 name에 대해 다음을 수행합니다.
      1. declaredVariableNames에 name이 포함되어 있지 않으면, 다음을 수행합니다.
        1. ! envRecord.CreateMutableBinding(name, false)를 수행합니다.
        2. ! envRecord.InitializeBinding(name, undefined)를 수행합니다.
        3. name을 declaredVariableNames에 추가합니다.
  22. lexicalDecls를 code의 LexicallyScopedDeclarations로 둡니다.
  23. privateEnv를 null로 둡니다.
  24. lexicalDecls의 각 요소 lexicalDecl에 대해 다음을 수행합니다.
    1. lexicalDecl의 BoundNames의 각 요소 name에 대해 다음을 수행합니다.
      1. lexicalDecl의 IsConstantDeclaration이 true이면, 다음을 수행합니다.
        1. ! envRecord.CreateImmutableBinding(name, true)를 수행합니다.
      2. 그렇지 않으면,
        1. ! envRecord.CreateMutableBinding(name, false)를 수행합니다.
      3. lexicalDecl이 FunctionDeclaration, GeneratorDeclaration, AsyncFunctionDeclaration 또는 AsyncGeneratorDeclaration 중 하나이면, 다음을 수행합니다.
        1. funcObj를 인수 envRecord 및 privateEnv를 사용한 lexicalDecl의 InstantiateFunctionObject로 둡니다.
        2. ! envRecord.InitializeBinding(name, funcObj)를 수행합니다.
  25. moduleContext를 실행 컨텍스트 스택에서 제거합니다.
  26. unused를 반환합니다.

16.2.1.7.3.2 ExecuteModule ( [ capability ] )

a Source Text Module Record module의 구체 메서드 ExecuteModule. 선택적 인수 capability (PromiseCapability 레코드). 반환값: (정상 완료 (값: unused) 또는 throw 완료). 호출되면 다음 단계를 수행한다.

  1. 단언: module은 연결되었으며 해당 모듈 환경의 선언이 인스턴스화되어 있습니다.
  2. moduleContext를 module.[[Context]]로 둡니다.
  3. module.[[HasTLA]]가 false이면, 다음을 수행합니다.
    1. 단언: capability은 존재하지 않습니다.
    2. env를 module.[[Environment]]로 둡니다.
    3. 실행 중인 실행 컨텍스트를 일시 중단합니다.
    4. moduleContext를 실행 컨텍스트 스택에 푸시합니다. 이제 moduleContext가 실행 중인 실행 컨텍스트입니다.
    5. result를 Completion(module.[[ECMAScriptCode]]의 Evaluation)으로 둡니다.
    6. result를 Completion(DisposeResources(env.[[DisposableResourceStack]], result))으로 설정합니다.
    7. moduleContext를 일시 중단하고 실행 컨텍스트 스택에서 제거합니다.
    8. 이제 실행 컨텍스트 스택의 맨 위에 있는 컨텍스트를 실행 중인 실행 컨텍스트로 재개합니다.
    9. result가 비정상 완료이면, 다음을 수행합니다.
      1. ? result를 반환합니다.
  4. 그렇지 않으면,
    1. 단언: capability은 PromiseCapability Record입니다.
    2. AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext)를 수행합니다.
  5. unused를 반환합니다.

16.2.1.8 Synthetic Module Record

Synthetic Module Record는 명세에 의해 정의된 모듈에 관한 정보를 나타내는 데 사용됩니다. 내보낸 이름은 생성 시 정적으로 정의되지만 대응 값은 SetSyntheticModuleExport를 사용하여 시간에 따라 변경될 수 있습니다. import나 종속성은 없습니다.

참고
Synthetic Module Record는 다양한 종류의 모듈, 예를 들어 JSON 모듈이나 CSS 모듈을 정의하는 데 사용할 수 있습니다.

표 39에 정의된 필드 외에도 Synthetic Module Record에는 표 58에 나열된 추가 필드가 있습니다.

표 58: Synthetic Module Record의 추가 필드
필드 이름 값 타입 의미
[[ExportNames]] a List of Strings 모듈의 export 이름입니다. 이 목록에는 중복 항목이 없습니다.
[[EvaluationSteps]] an Abstract Closure 모듈 평가 시 수행할 초기화 로직이며 Synthetic Module Record를 유일한 인수로 받습니다. [[ExportNames]]를 수정해서는 안 됩니다. 비정상 완료를 반환할 수 있습니다.

16.2.1.8.1 CreateDefaultExportSyntheticModule ( defaultExport )

추상 연산 CreateDefaultExportSyntheticModule. 인수 defaultExport (ECMAScript 언어 값). 반환값: Synthetic Module 레코드. 기본 export가 defaultExport인 Synthetic Module Record를 생성합니다. 호출되면 다음 단계를 수행한다.

  1. realm을 현재 Realm Record로 둡니다.
  2. setDefaultExport를 매개변수 (module)를 갖고 defaultExport를 캡처하며 호출될 때 다음 단계를 수행하는 새로운 Abstract Closure로 둡니다:
    1. SetSyntheticModuleExport(module, "default", defaultExport)를 수행합니다.
    2. NormalCompletion(unused)을 반환합니다.
  3. Synthetic Module Record { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[HostDefined]]: undefined, [[ExportNames]]: « "default" », [[EvaluationSteps]]: setDefaultExport }를 반환합니다.

16.2.1.8.2 ParseJSONModule ( source )

추상 연산 ParseJSONModule. 인수 source (String). 반환값: (정상 완료 (값: Synthetic Module 레코드) 또는 throw 완료). 호출되면 다음 단계를 수행한다.

  1. parseResult를 ? ParseJSON(source)로 둡니다.
  2. CreateDefaultExportSyntheticModule(parseResult.[[Value]])을 반환합니다.

16.2.1.8.3 SetSyntheticModuleExport ( module, exportName, exportValue )

추상 연산 SetSyntheticModuleExport. 인수 module (Synthetic Module 레코드), exportName (String) 및 exportValue (ECMAScript 언어 값). 반환값: unused. Synthetic Module Record의 기존 export에 대해 내보내는 값을 설정하거나 변경하는 데 사용할 수 있습니다. 호출되면 다음 단계를 수행한다.

  1. 단언: module.[[ExportNames]]에 exportName이 포함되어 있습니다.
  2. envRecord를 module.[[Environment]]로 둡니다.
  3. 단언: envRecord는 empty가 아닙니다.
  4. ! envRecord.SetMutableBinding(exportName, exportValue, true)를 수행합니다.
  5. unused를 반환합니다.

16.2.1.8.4 Module Record 추상 메서드의 구현

다음은 표 40에 정의된 대응 Module Record 추상 메서드를 구현하는 Synthetic Module Record의 구체 메서드입니다.

16.2.1.8.4.1 LoadRequestedModules ( [ hostDefined ] )

a Synthetic Module Record module의 구체 메서드 LoadRequestedModules. 선택적 인수 hostDefined (임의의 값). 반환값: Promise. 호출되면 다음 단계를 수행한다.

  1. 참고: 이 LoadRequestedModules 구현은 hostDefined를 사용하지 않습니다.
  2. ! PromiseResolve(%Promise%, undefined)를 반환합니다.
참고
Synthetic Module Record에는 종속성이 없습니다.

16.2.1.8.4.2 GetExportedNames ( [ exportStarSet ] )

a Synthetic Module Record module의 구체 메서드 GetExportedNames. 선택적 인수 exportStarSet (리스트 (요소: Source Text Module 레코드)). 반환값: 리스트 (요소: String). 호출되면 다음 단계를 수행한다.

  1. 참고: 이 GetExportedNames 구현은 exportStarSet을 사용하지 않습니다.
  2. module.[[ExportNames]]를 반환합니다.

16.2.1.8.4.3 ResolveExport ( exportName [ , resolveSet ] )

a Synthetic Module Record module의 구체 메서드 ResolveExport. 인수 exportName (String) 및 선택적 인수 resolveSet (리스트 (요소: 레코드 (필드: [[Module]] (Module 레코드), [[ExportName]] (String)))). 반환값: (ResolvedBinding 레코드, null 또는 ambiguous). 호출되면 다음 단계를 수행한다.

  1. 참고: 이 ResolveExport 구현은 resolveSet을 사용하지 않습니다.
  2. module.[[ExportNames]]에 exportName이 포함되어 있지 않으면 null을 반환합니다.
  3. ResolvedBinding Record { [[Module]]: module, [[BindingName]]: exportName }을 반환합니다.

16.2.1.8.4.4 Link ( )

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

  1. realm을 module.[[Realm]]으로 둡니다.
  2. envRecord를 NewModuleEnvironment(realm.[[GlobalEnv]])로 둡니다.
  3. module.[[Environment]]를 envRecord로 설정합니다.
  4. module.[[ExportNames]]의 각 String exportName에 대해 다음을 수행합니다.
    1. ! envRecord.CreateMutableBinding(exportName, false)를 수행합니다.
    2. ! envRecord.InitializeBinding(exportName, undefined)를 수행합니다.
  5. NormalCompletion(unused)을 반환합니다.

16.2.1.8.4.5 Evaluate ( )

a Synthetic Module Record module의 구체 메서드 Evaluate. 인수 없음. 반환값: Promise. 호출되면 다음 단계를 수행한다.

  1. moduleContext를 새로운 ECMAScript 코드 실행 컨텍스트로 둡니다.
  2. moduleContext의 Function을 null로 설정합니다.
  3. moduleContext의 Realm을 module.[[Realm]]으로 설정합니다.
  4. moduleContext의 ScriptOrModule을 module로 설정합니다.
  5. moduleContext의 VariableEnvironment를 module.[[Environment]]로 설정합니다.
  6. moduleContext의 LexicalEnvironment를 module.[[Environment]]로 설정합니다.
  7. 실행 중인 실행 컨텍스트를 일시 중단합니다.
  8. moduleContext를 실행 컨텍스트 스택에 푸시합니다. 이제 moduleContext가 실행 중인 실행 컨텍스트입니다.
  9. steps를 module.[[EvaluationSteps]]로 둡니다.
  10. result를 Completion(steps(module))으로 둡니다.
  11. moduleContext를 일시 중단하고 실행 컨텍스트 스택에서 제거합니다.
  12. 이제 실행 컨텍스트 스택의 맨 위에 있는 컨텍스트를 실행 중인 실행 컨텍스트로 재개합니다.
  13. promiseCapability을 ! NewPromiseCapability(%Promise%)로 둡니다.
  14. IfAbruptRejectPromise(result, promiseCapability).
  15. ! Call(promiseCapability.[[Resolve]], undefined, « undefined »)를 수행합니다.
  16. promiseCapability.[[Promise]]를 반환합니다.

16.2.1.9 GetImportedModule ( referrer, request )

추상 연산 GetImportedModule. 인수 referrer (Cyclic Module 레코드) 및 request (ModuleRequest 레코드). 반환값: Module 레코드. 호출되면 다음 단계를 수행한다.

  1. records를 referrer.[[LoadedModules]]의 각 LoadedModuleRequest Record r 중 ModuleRequestsEqual(r, request)이 true인 것들로 구성된 List로 둡니다.
  2. 단언: 이 추상 연산을 호출하기 전에 referrer에서 LoadRequestedModules가 성공적으로 완료되었으므로 records에는 정확히 하나의 요소가 있습니다.
  3. record를 records의 유일한 요소로 둡니다.
  4. record.[[Module]]을 반환합니다.

16.2.1.10 HostLoadImportedModule ( referrer, moduleRequest, hostDefined, payload )

호스트 정의 추상 연산 HostLoadImportedModule. 인수 referrer ((Script 레코드, Cyclic Module 레코드 또는 Realm 레코드)), moduleRequest (ModuleRequest 레코드), hostDefined (임의의 값) 및 payload ((GraphLoadingState 레코드 또는 PromiseCapability 레코드)). 반환값: unused.

참고 1

referrer가 Realm Record일 수 있는 예로 웹 브라우저 호스트를 들 수 있습니다. 여기서 사용자가 다음과 같이 주어진 컨트롤을 클릭하면

<button type="button" onclick="import('./foo.mjs')">Click me</button>

import() 표현식이 실행될 때 활성 스크립트 또는 모듈이 존재하지 않습니다. 더 일반적으로 이는 호스트가 null ScriptOrModule 구성 요소를 갖는 실행 컨텍스트를 실행 컨텍스트 스택에 푸시하는 모든 상황에서 발생할 수 있습니다.

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

실제로 수행되는 과정은 호스트 정의이지만 일반적으로 적절한 Module Record를 로드하는 데 필요한 I/O 연산을 수행하는 것으로 구성됩니다. 서로 다른 여러 (referrer, moduleRequest.[[Specifier]], moduleRequest.[[Attributes]]) 트리플이 동일한 Module Record 인스턴스로 매핑될 수 있습니다. 실제 매핑 의미론은 호스트 정의이지만 일반적으로 매핑 과정의 일부로 specifier에 정규화 과정을 적용합니다. 일반적인 정규화 과정에는 상대 경로 및 축약 경로 지정자의 확장과 같은 작업이 포함됩니다.

참고 2

위 텍스트는 type: "json"으로 가져오는 경우(그리고 HostLoadImportedModule이 정상 완료하는 경우) 호스트가 JSON 모듈을 지원하도록 요구하지만, type: "json" 없이 가져오는 경우 JSON 모듈을 지원하는 것을 금지하지는 않습니다.

16.2.1.11 FinishLoadingImportedModule ( referrer, moduleRequest, payload, result )

추상 연산 FinishLoadingImportedModule. 인수 referrer ((Script 레코드, Cyclic Module 레코드 또는 Realm 레코드)), moduleRequest (ModuleRequest 레코드), payload ((GraphLoadingState 레코드 또는 PromiseCapability 레코드)) 및 result ((정상 완료 (값: Module 레코드) 또는 throw 완료)). 반환값: unused. 호출되면 다음 단계를 수행한다.

  1. result가 정상 완료이면, 다음을 수행합니다.
    1. referrer.[[LoadedModules]]에 ModuleRequestsEqual(record, moduleRequest)이 true인 LoadedModuleRequest Record record가 포함되어 있으면, 다음을 수행합니다.
      1. 단언: record.[[Module]]과 result.[[Value]]는 동일한 Module Record입니다.
    2. 그렇지 않으면,
      1. LoadedModuleRequest Record { [[Specifier]]: moduleRequest.[[Specifier]], [[Attributes]]: moduleRequest.[[Attributes]], [[Module]]: result.[[Value]] }를 referrer.[[LoadedModules]]에 추가합니다.
  2. payload가 GraphLoadingState Record이면, 다음을 수행합니다.
    1. ContinueModuleLoading(payload, result)을 수행합니다.
  3. 그렇지 않으면,
    1. ContinueDynamicImport(payload, result)을 수행합니다.
  4. unused를 반환합니다.

16.2.1.12 AllImportAttributesSupported ( attrs )

추상 연산 AllImportAttributesSupported. 인수 attrs (리스트 (요소: ImportAttribute 레코드)). 반환값: Boolean. 호출되면 다음 단계를 수행한다.

  1. supported를 HostGetSupportedImportAttributes()로 둡니다.
  2. attrs의 각 ImportAttribute Record attr에 대해 다음을 수행합니다.
    1. supported에 attr.[[Key]]가 포함되어 있지 않으면 false를 반환합니다.
  3. true를 반환합니다.

16.2.1.12.1 HostGetSupportedImportAttributes ( )

호스트 정의 추상 연산 HostGetSupportedImportAttributes. 인수 없음. 반환값: 리스트 (요소: String). 호스트 환경이 어떤 import 속성을 지원하는지 명시할 수 있도록 합니다. 지원되는 키를 갖는 속성만 호스트에 제공됩니다.

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

  • 지원되는 속성을 각각 나타내는 String의 List를 반환해야 합니다.
  • 이 연산을 호출할 때마다 동일한 내용과 동일한 순서의 같은 List를 반환해야 합니다.

HostGetSupportedImportAttributes의 기본 구현은 새로운 빈 List를 반환합니다.

참고
모든 속성을 호스트에 전달한 뒤 호스트가 처리할 속성을 선택하게 하지 않고 호스트가 지원하는 import 속성을 명시하도록 요구하는 목적은 지원되지 않는 속성이 서로 다른 호스트에서 일관된 방식으로 처리되도록 보장하기 위한 것입니다.

16.2.1.13 GetModuleNamespace ( module )

추상 연산 GetModuleNamespace. 인수 module (instance of a concrete subclass of Module 레코드). 반환값: a Module Namespace Object. module의 export를 나타내는 Module Namespace Object를 가져오며, 처음 요청될 때 지연 생성하고 향후 조회를 위해 module.[[Namespace]]에 저장합니다. 호출되면 다음 단계를 수행한다.

  1. 단언: module이 Cyclic Module Record이면 module.[[Status]]는 new 또는 unlinked가 아닙니다.
  2. namespace를 module.[[Namespace]]로 둡니다.
  3. namespace가 empty이면, 다음을 수행합니다.
    1. exportedNames를 module.GetExportedNames()로 둡니다.
    2. unambiguousNames를 새로운 빈 List로 둡니다.
    3. exportedNames의 각 요소 name에 대해 다음을 수행합니다.
      1. resolution을 module.ResolveExport(name)로 둡니다.
      2. resolution이 ResolvedBinding Record이면 name을 unambiguousNames에 추가합니다.
    4. namespace를 ModuleNamespaceCreate(module, unambiguousNames)로 설정합니다.
  4. namespace를 반환합니다.
참고

GetModuleNamespace는 절대로 예외를 던지지 않습니다. 대신 해석할 수 없는 이름은 이 시점에서 네임스페이스에서 단순히 제외됩니다. 이러한 이름이 어디에서도 명시적으로 요청되지 않은 모호한 star export가 전부인 경우를 제외하면 나중에 실제 연결 오류를 일으킵니다.

16.2.1.14 Runtime Semantics: 평가

Module : [empty]
  1. undefined를 반환합니다.
ModuleBody : ModuleItemList
  1. result를 Completion(ModuleItemList의 Evaluation)으로 둡니다.
  2. result가 정상 완료이고 result.[[Value]]가 empty이면, 다음을 수행합니다.
    1. undefined를 반환합니다.
  3. ? result를 반환합니다.
ModuleItemList : ModuleItemList ModuleItem
  1. sl을 ModuleItemList의 ? Evaluation으로 둡니다.
  2. s를 Completion(ModuleItem의 Evaluation)으로 둡니다.
  3. ? UpdateEmpty(s, sl)을 반환합니다.
참고

ModuleItemList의 값은 ModuleItemList에서 값을 생성하는 마지막 항목의 값입니다.

ModuleItem : ImportDeclaration
  1. empty를 반환합니다.

16.2.2 Import

구문

ImportDeclaration : import ImportClause FromClause WithClauseopt ; import ModuleSpecifier WithClauseopt ; ImportClause : ImportedDefaultBinding NameSpaceImport NamedImports ImportedDefaultBinding , NameSpaceImport ImportedDefaultBinding , NamedImports ImportedDefaultBinding : ImportedBinding NameSpaceImport : * as ImportedBinding NamedImports : { } { ImportsList ,opt } FromClause : from ModuleSpecifier ImportsList : ImportSpecifier ImportsList , ImportSpecifier ImportSpecifier : ImportedBinding ModuleExportName as ImportedBinding ModuleSpecifier : StringLiteral ImportedBinding : BindingIdentifier[~Yield, +Await] WithClause : with { } with { WithEntries ,opt } WithEntries : AttributeKey : StringLiteral AttributeKey : StringLiteral , WithEntries AttributeKey : IdentifierName StringLiteral

16.2.2.1 Static Semantics: 조기 오류

ModuleItem : ImportDeclaration WithClause : with { WithEntries ,opt }

16.2.2.2 Static Semantics: ImportEntries

구문 지향 연산 ImportEntries. 인수 없음. 반환값: 리스트 (요소: ImportEntry 레코드). 다음 생성 규칙별로 정의된다.

Module : [empty]
  1. 새로운 빈 List를 반환합니다.
ModuleItemList : ModuleItemList ModuleItem
  1. entries1을 ModuleItemList의 ImportEntries로 둡니다.
  2. entries2를 ModuleItem의 ImportEntries로 둡니다.
  3. entries1과 entries2의 목록 연결을 반환합니다.
ModuleItem : ExportDeclaration StatementListItem
  1. 새로운 빈 List를 반환합니다.
ImportDeclaration : import ImportClause FromClause WithClauseopt ;
  1. module을 ImportDeclaration의 ModuleRequests의 유일한 요소로 둡니다.
  2. 인수 module을 사용한 ImportClause의 ImportEntriesForModule을 반환합니다.
ImportDeclaration : import ModuleSpecifier WithClauseopt ;
  1. 새로운 빈 List를 반환합니다.

16.2.2.3 Static Semantics: ImportEntriesForModule

구문 지향 연산 ImportEntriesForModule. 인수 module (ModuleRequest 레코드). 반환값: 리스트 (요소: ImportEntry 레코드). 다음 생성 규칙별로 정의된다.

ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. entries1을 인수 module을 사용한 ImportedDefaultBinding의 ImportEntriesForModule로 둡니다.
  2. entries2를 인수 module을 사용한 NameSpaceImport의 ImportEntriesForModule로 둡니다.
  3. entries1과 entries2의 목록 연결을 반환합니다.
ImportClause : ImportedDefaultBinding , NamedImports
  1. entries1을 인수 module을 사용한 ImportedDefaultBinding의 ImportEntriesForModule로 둡니다.
  2. entries2를 인수 module을 사용한 NamedImports의 ImportEntriesForModule로 둡니다.
  3. entries1과 entries2의 목록 연결을 반환합니다.
ImportedDefaultBinding : ImportedBinding
  1. localName을 ImportedBinding의 BoundNames의 유일한 요소로 둡니다.
  2. defaultEntry를 ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: "default", [[LocalName]]: localName }로 둡니다.
  3. « defaultEntry »을 반환합니다.
NameSpaceImport : * as ImportedBinding
  1. localName을 ImportedBinding의 StringValue로 둡니다.
  2. entry를 ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: namespace, [[LocalName]]: localName }로 둡니다.
  3. « entry »을 반환합니다.
NamedImports : { }
  1. 새로운 빈 List를 반환합니다.
ImportsList : ImportsList , ImportSpecifier
  1. specs1을 인수 module을 사용한 ImportsList의 ImportEntriesForModule로 둡니다.
  2. specs2를 인수 module을 사용한 ImportSpecifier의 ImportEntriesForModule로 둡니다.
  3. specs1과 specs2의 목록 연결을 반환합니다.
ImportSpecifier : ImportedBinding
  1. localName을 ImportedBinding의 BoundNames의 유일한 요소로 둡니다.
  2. entry를 ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: localName, [[LocalName]]: localName }로 둡니다.
  3. « entry »을 반환합니다.
ImportSpecifier : ModuleExportName as ImportedBinding
  1. importName을 ModuleExportName의 StringValue로 둡니다.
  2. localName을 ImportedBinding의 StringValue로 둡니다.
  3. entry를 ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName }로 둡니다.
  4. « entry »을 반환합니다.

16.2.2.4 Static Semantics: WithClauseToAttributes

구문 지향 연산 WithClauseToAttributes. 인수 없음. 반환값: 리스트 (요소: ImportAttribute 레코드). 다음 생성 규칙별로 정의된다.

WithClause : with { }
  1. 새로운 빈 List를 반환합니다.
WithClause : with { WithEntries ,opt }
  1. attrs를 WithEntries의 WithClauseToAttributes로 둡니다.
  2. 각 [[Key]] 필드 값을 UTF-16 코드 단위 값의 시퀀스로 취급하여 해당 [[Key]] 필드의 사전식 순서에 따라 attrs를 정렬합니다. 참고: 호스트가 속성이 열거되는 순서를 기반으로 동작을 변경하는 것이 금지되어 있다는 점에서만 이 정렬을 관찰할 수 있습니다.
  3. attrs를 반환합니다.
WithEntries : AttributeKey : StringLiteral
  1. key를 AttributeKey의 PropName으로 둡니다.
  2. entry를 ImportAttribute Record { [[Key]]: key, [[Value]]: StringLiteral의 SV }로 둡니다.
  3. « entry »을 반환합니다.
WithEntries : AttributeKey : StringLiteral , WithEntries
  1. key를 AttributeKey의 PropName으로 둡니다.
  2. entry를 ImportAttribute Record { [[Key]]: key, [[Value]]: StringLiteral의 SV }로 둡니다.
  3. rest를 WithEntries의 WithClauseToAttributes로 둡니다.
  4. « entry »과 rest의 목록 연결을 반환합니다.

16.2.3 Export

구문

ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ; export VariableStatement[~Yield, +Await] export [lookahead ∉ { using, await }] Declaration[~Yield, +Await] export default HoistableDeclaration[~Yield, +Await, +Default] export default ClassDeclaration[~Yield, +Await, +Default] export default [lookahead ∉ { function, async [no LineTerminator here] function, class }] AssignmentExpression[+In, ~Yield, +Await] ; ExportFromClause : * * as ModuleExportName NamedExports NamedExports : { } { ExportsList ,opt } ExportsList : ExportSpecifier ExportsList , ExportSpecifier ExportSpecifier : ModuleExportName ModuleExportName as ModuleExportName

16.2.3.1 Static Semantics: 조기 오류

ExportDeclaration : export NamedExports ; 참고

위 규칙은 NamedExports의 각 ReferencedBindings를 IdentifierReference처럼 취급한다는 의미입니다.

16.2.3.2 Static Semantics: ExportedBindings

구문 지향 연산 ExportedBindings. 인수 없음. 반환값: 리스트 (요소: String).

참고

ExportedBindings는 Module의 ExportedNames와 명시적으로 연결된 로컬 바인딩 이름입니다.

다음 생성 규칙별로 정의된다.

ModuleItemList : ModuleItemList ModuleItem
  1. names1을 ModuleItemList의 ExportedBindings로 둡니다.
  2. names2를 ModuleItem의 ExportedBindings로 둡니다.
  3. names1과 names2의 목록 연결을 반환합니다.
ModuleItem : ImportDeclaration StatementListItem
  1. 새로운 빈 List를 반환합니다.
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 새로운 빈 List를 반환합니다.
ExportDeclaration : export NamedExports ;
  1. NamedExports의 ExportedBindings를 반환합니다.
ExportDeclaration : export VariableStatement
  1. VariableStatement의 BoundNames를 반환합니다.
ExportDeclaration : export Declaration
  1. Declaration의 BoundNames를 반환합니다.
ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 이 ExportDeclaration의 BoundNames를 반환합니다.
NamedExports : { }
  1. 새로운 빈 List를 반환합니다.
ExportsList : ExportsList , ExportSpecifier
  1. names1을 ExportsList의 ExportedBindings로 둡니다.
  2. names2를 ExportSpecifier의 ExportedBindings로 둡니다.
  3. names1과 names2의 목록 연결을 반환합니다.
ExportSpecifier : ModuleExportName
  1. 유일한 요소가 ModuleExportName의 StringValue인 List를 반환합니다.
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 유일한 요소가 첫 번째 ModuleExportName의 StringValue인 List를 반환합니다.

16.2.3.3 Static Semantics: ExportedNames

구문 지향 연산 ExportedNames. 인수 없음. 반환값: 리스트 (요소: String).

참고

ExportedNames는 Module이 자신의 로컬 이름 바인딩 중 하나에 명시적으로 매핑하는 외부에서 볼 수 있는 이름입니다.

다음 생성 규칙별로 정의된다.

ModuleItemList : ModuleItemList ModuleItem
  1. names1을 ModuleItemList의 ExportedNames로 둡니다.
  2. names2를 ModuleItem의 ExportedNames로 둡니다.
  3. names1과 names2의 목록 연결을 반환합니다.
ModuleItem : ExportDeclaration
  1. ExportDeclaration의 ExportedNames를 반환합니다.
ModuleItem : ImportDeclaration StatementListItem
  1. 새로운 빈 List를 반환합니다.
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. ExportFromClause의 ExportedNames를 반환합니다.
ExportFromClause : *
  1. 새로운 빈 List를 반환합니다.
ExportFromClause : * as ModuleExportName
  1. 유일한 요소가 ModuleExportName의 StringValue인 List를 반환합니다.
ExportFromClause : NamedExports
  1. NamedExports의 ExportedNames를 반환합니다.
ExportDeclaration : export VariableStatement
  1. VariableStatement의 BoundNames를 반환합니다.
ExportDeclaration : export Declaration
  1. Declaration의 BoundNames를 반환합니다.
ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. « "default" »를 반환합니다.
NamedExports : { }
  1. 새로운 빈 List를 반환합니다.
ExportsList : ExportsList , ExportSpecifier
  1. names1을 ExportsList의 ExportedNames로 둡니다.
  2. names2를 ExportSpecifier의 ExportedNames로 둡니다.
  3. names1과 names2의 목록 연결을 반환합니다.
ExportSpecifier : ModuleExportName
  1. 유일한 요소가 ModuleExportName의 StringValue인 List를 반환합니다.
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 유일한 요소가 두 번째 ModuleExportName의 StringValue인 List를 반환합니다.

16.2.3.4 Static Semantics: ExportEntries

구문 지향 연산 ExportEntries. 인수 없음. 반환값: 리스트 (요소: ExportEntry 레코드). 다음 생성 규칙별로 정의된다.

Module : [empty]
  1. 새로운 빈 List를 반환합니다.
ModuleItemList : ModuleItemList ModuleItem
  1. entries1을 ModuleItemList의 ExportEntries로 둡니다.
  2. entries2를 ModuleItem의 ExportEntries로 둡니다.
  3. entries1과 entries2의 목록 연결을 반환합니다.
ModuleItem : ImportDeclaration StatementListItem
  1. 새로운 빈 List를 반환합니다.
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. module을 ExportDeclaration의 ModuleRequests의 유일한 요소로 둡니다.
  2. 인수 module을 사용한 ExportFromClause의 ExportEntriesForModule을 반환합니다.
ExportDeclaration : export NamedExports ;
  1. 인수 null을 사용한 NamedExports의 ExportEntriesForModule을 반환합니다.
ExportDeclaration : export VariableStatement
  1. entries를 새로운 빈 List로 둡니다.
  2. names를 VariableStatement의 BoundNames로 둡니다.
  3. names의 각 요소 name에 대해 다음을 수행합니다.
    1. ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name }을 entries에 추가합니다.
  4. entries를 반환합니다.
ExportDeclaration : export Declaration
  1. entries를 새로운 빈 List로 둡니다.
  2. names를 Declaration의 BoundNames로 둡니다.
  3. names의 각 요소 name에 대해 다음을 수행합니다.
    1. ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name }을 entries에 추가합니다.
  4. entries를 반환합니다.
ExportDeclaration : export default HoistableDeclaration
  1. names를 HoistableDeclaration의 BoundNames로 둡니다.
  2. localName을 names의 유일한 요소로 둡니다.
  3. 유일한 요소가 새로운 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" }인 List를 반환합니다.
ExportDeclaration : export default ClassDeclaration
  1. names를 ClassDeclaration의 BoundNames로 둡니다.
  2. localName을 names의 유일한 요소로 둡니다.
  3. 유일한 요소가 새로운 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" }인 List를 반환합니다.
ExportDeclaration : export default AssignmentExpression ;
  1. entry를 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: "*default*", [[ExportName]]: "default" }로 둡니다.
  2. « entry »을 반환합니다.
참고

"*default*"는 이 명세 안에서 익명 기본 export 값의 합성 이름으로 사용됩니다. 자세한 내용은 이 참고를 참조하시기 바랍니다.

16.2.3.5 Static Semantics: ExportEntriesForModule

구문 지향 연산 ExportEntriesForModule. 인수 module ((ModuleRequest 레코드 또는 null)). 반환값: 리스트 (요소: ExportEntry 레코드). 다음 생성 규칙별로 정의된다.

ExportFromClause : *
  1. entry를 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: all-but-default, [[LocalName]]: null, [[ExportName]]: null }로 둡니다.
  2. « entry »을 반환합니다.
ExportFromClause : * as ModuleExportName
  1. exportName을 ModuleExportName의 StringValue로 둡니다.
  2. entry를 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: namespace, [[LocalName]]: null, [[ExportName]]: exportName }로 둡니다.
  3. « entry »을 반환합니다.
NamedExports : { }
  1. 새로운 빈 List를 반환합니다.
ExportsList : ExportsList , ExportSpecifier
  1. specs1을 인수 module을 사용한 ExportsList의 ExportEntriesForModule로 둡니다.
  2. specs2를 인수 module을 사용한 ExportSpecifier의 ExportEntriesForModule로 둡니다.
  3. specs1과 specs2의 목록 연결을 반환합니다.
ExportSpecifier : ModuleExportName
  1. sourceName을 ModuleExportName의 StringValue로 둡니다.
  2. module이 null이면, 다음을 수행합니다.
    1. localName을 sourceName으로 둡니다.
    2. importName을 null로 둡니다.
  3. 그렇지 않으면,
    1. localName을 null로 둡니다.
    2. importName을 sourceName으로 둡니다.
  4. 유일한 요소가 새로운 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: sourceName }인 List를 반환합니다.
ExportSpecifier : ModuleExportName as ModuleExportName
  1. sourceName을 첫 번째 ModuleExportName의 StringValue로 둡니다.
  2. exportName을 두 번째 ModuleExportName의 StringValue로 둡니다.
  3. module이 null이면, 다음을 수행합니다.
    1. localName을 sourceName으로 둡니다.
    2. importName을 null로 둡니다.
  4. 그렇지 않으면,
    1. localName을 null로 둡니다.
    2. importName을 sourceName으로 둡니다.
  5. 유일한 요소가 새로운 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: exportName }인 List를 반환합니다.

16.2.3.6 Static Semantics: ReferencedBindings

구문 지향 연산 ReferencedBindings. 인수 없음. 반환값: 리스트 (요소: 구문 분석 노드). 다음 생성 규칙별로 정의된다.

NamedExports : { }
  1. 새로운 빈 List를 반환합니다.
ExportsList : ExportsList , ExportSpecifier
  1. names1을 ExportsList의 ReferencedBindings로 둡니다.
  2. names2를 ExportSpecifier의 ReferencedBindings로 둡니다.
  3. names1과 names2의 목록 연결을 반환합니다.
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 첫 번째 ModuleExportName의 ReferencedBindings를 반환합니다.
ModuleExportName : IdentifierName
  1. 유일한 요소가 IdentifierName인 List를 반환합니다.
ModuleExportName : StringLiteral
  1. 유일한 요소가 StringLiteral인 List를 반환합니다.

16.2.3.7 Runtime Semantics: 평가

ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ;
  1. empty를 반환합니다.
ExportDeclaration : export VariableStatement
  1. VariableStatement의 ? Evaluation을 반환합니다.
ExportDeclaration : export Declaration
  1. Declaration의 ? Evaluation을 반환합니다.
ExportDeclaration : export default HoistableDeclaration
  1. HoistableDeclaration의 ? Evaluation을 반환합니다.
ExportDeclaration : export default ClassDeclaration
  1. value를 ClassDeclaration의 ? BindingClassDeclarationEvaluation으로 둡니다.
  2. className을 ClassDeclaration의 BoundNames의 유일한 요소로 둡니다.
  3. className이 "*default*"이면, 다음을 수행합니다.
    1. envRecord를 실행 중인 실행 컨텍스트의 LexicalEnvironment로 둡니다.
    2. ? InitializeBoundName("*default*", value, envRecord)를 수행합니다.
  4. empty를 반환합니다.
ExportDeclaration : export default AssignmentExpression ;
  1. IsAnonymousFunctionDefinition(AssignmentExpression)이 true이면, 다음을 수행합니다.
    1. value를 인수 "default"를 사용한 AssignmentExpression의 ? NamedEvaluation으로 둡니다.
  2. 그렇지 않으면,
    1. rhs를 AssignmentExpression의 ? Evaluation으로 둡니다.
    2. value를 ? GetValue(rhs)로 둡니다.
  3. envRecord를 실행 중인 실행 컨텍스트의 LexicalEnvironment로 둡니다.
  4. ? InitializeBoundName("*default*", value, envRecord)를 수행합니다.
  5. empty를 반환합니다.