명세를 향한 여정
Michael Gardner와 Randy Solton은 11월 회의 직후 첫번째 명세 초안의 작업을 시작했다. 그리고 이후 6주간 놀라운 진전을 이뤘다. Gardner와 Solton 외에도 첫번째 초안에는 다음과 같은 기술 기여자들이 적혀 있다. Brendan Eich(Netscape), C. Rand McKinney(Netscape), Donna Converse(Netscape), Shon Katzenberger(Microsoft), Robert Welland (Microsoft).
Robert Welland는 Redmond로 돌아가서 자신이 만든 JScript 0.1 명세를 Shon Katzenberger에게 맡겨 계속 개발하도록 하였다 [Welland et al. 2018, at 12:02]. 수학 박사였던 Katzenberger는 형식적인 표기법에 익숙했고, Javascript 시맨틱을 기술하는 데에 의사 코드 개념(부록 P)이 잘 맞다고 판단했다. 의사 코드는 Katzenberger가 생각하기에 상호 호환성을 보장할 만큼의 충분한 세부사항을 제공했다. Katzenberger는 표준 개발에 있어서 Microsoft의 주요한 기술 기여자가 되었다. Katzenberger는 Welland와 Smith가 늦은 밤 작업한 것을 실행 중인 구현과 비교 검토하고, 그들이 다루지 않았던 부분들에 대한 추가적인 의사 코드 알고리즘을 작성하여 확장하였다. 그 다음 그렇게 새로 수정된 자료를 공식 초안에 포함시키기 위해 Borland 편집자들에게 전달하였다. 2018년 인터뷰에서 Katzenberger [Welland et al. 2018, at 21:16]는 명세 편집 과정에서 종종 자신의 알고리즘이 의도치 않게 망가졌다는 사실에 불만이 있었다고 회상했다. Guy Steele이 편집자로 활동하게 되자 그는 매우 만족했다.
1997년 1월 10일의 초안 [TC39 1997c]은 명세의 기본 구조(그림 13)를 확립하였다. 그리고 언어의 정의에 사용된 많은 기본적인 기술과 관례와 용어를 정의했다. 이때 만들어진 많은 부분은 20년이 지난 지금의 ECMAScript 표준에서도 여전히 사용되고 있다.
문법 규칙에 대한 설명은 대부분 Netscape가 작성한 사양에서 가져온 것이다. 하지만 표현식과 문장 문법의 구조와 생성 규칙은 대부분 Microsoft가 작성한 사양에서 사용된 것을 따랐다. 표현식 문법은 두 가지 기여 사항과 모두 달랐는데 함수 호출의 우선순위, 객체 생성(new 연산자), 객체 속성 접근 표현식 등의 세부 사항에서 차이가 있었다.
당시 초안은 자동 세미콜론 삽입(ASI)의 규칙을 파싱 과정의 에러 수정 과정으로 정확하게 정의하려고 시도한다. 문장 문법은 복합 문장이 아닌 문장에 대해서 문장 종결을 위한 세미콜론을 요구한다. 따라서 자동 세미콜론 삽입이 없으면 세미콜론을 빼먹을 시 구문 오류가 발생한다. ASI 명세는 Javascript 파서가 세미콜론이 있다고 가정하고 파싱을 다시 함으로써 구문 오류를 수정해야 할 때가 언제인지를 정의한다. 첫 번째 초안의 ASI 규칙은 불완전했고 이후의 초안과 ECMAScript 명세 판본에서 다시 정의되었다.
4.7.4 GetValue(V)
- 만약 Type(V)가 Reference가 아니면 V를 반환한다.
- GetBase(V)를 호출한다
2
의 결과가 null이면 런타임 에러를 발생시킨다.2
의 결과의 [[Get]] 내부 메서드를 호출한다. GetProperty(V)를 프로퍼티 이름으로, GetAccess(V)를 접근 모드로 전달한다.4
의 결과를 반환한다.그림 14. 2007년 1월 10일 ECMAScript 명세 초안의 의사 코드 알고리즘 [TC39 1997c, §4.7.4]이다. 2단계 설명 끝의 마침표는 원본 문서에서 누락되어 있다.
1월 10일의 초안에는 그림 14에서 볼 수 있는 것과 같은 Shon Katzenberger의 의사코드 알고리즘들이 포함되어 있다. 이 알고리즘은 여러 언어 구조의 시맨틱을 정의하기 위 해서 사용되었다. 알고리즘들은 순차적으로 번호가 매겨진 단계들과 그 단계들 간에 간단한 조건부 제어 흐름으로 구성되어 있다. 각 단계는 명령적인 산문형 문장으로 구성되어 있다. 각 단계를 서술하는 문장들은 자주 발생하는 동작들에 대해서 명세가 정의한 어휘들을 포함한 영어로 작성되었다. 알고리즘은 이름이 지정될 수 있고 명세의 다른 알고리즘에서 "호출"될 수 있다.
이 초안은 또한 알고리즘에서 사용되는 자료형을 정의한다. Number, Boolean, String, Object, Undefined, Null은 ECMAScript 프로그램에서 보이는 값의 종류들이다. Reference, Completion, List 유형의 값은 언어 시맨틱을 정의하는 데 사용되며 ECMAScript 프로그램에 직접적으로 포함되어 있지는 않다.
객체 자료형의 명세는 개별 속성이 어떻게 접근되고 수정되는지를 제어하는 속성 어트리뷰트g(attribute)의 개념을 소개한다. 그리고 7가지 어트리뷰트를 정의한다. 그것들은 ReadOnly, ErrorOnWrite, DontEnum, NotImplicit, NotExplicit, Permanent, Internal로 총 7가지였다. 최종적으로는 ErrorOnWrite, NotImplicit, NotExplicit은 제거되었고 Permanent는 DontDelete로 이름이 변경되었다. 객체 속성들은 이런 각각의 내부 속성들을 가지고 있는데 이런 내부 속성들은 ECMAScript 프로그램에서 직접 드러나 있지는 않다. 하지만 이런 내부 속성들(internal propertiesg)는 객체 시맨틱이나 내장 및 호스트 객체의 고유한 동작을 구현하는 데에 필요한 상태를 유지하는 데에 사용된다.
내부 메서드g 개념도 도입되었다. 이는 객체의 필수적인 동작들을 정의하는 알고리즘이다. 다양한 종류의 객체들(예를 들어 Array 객체)은 몇몇 내부 메서드를 다르게 정의함으로써 동작의 다양성을 제공할 수 있다. 내부 메서드의 인터페이스는 기본적으로 간단한 메타오브젝트 프로토콜g 사양이다 [Kiczales et al. 1991].
명세에서 내부 메소드와 내부 속성은 [[Foo]]
와 같이 이중 괄호로 둘러싸인 이름을 가진다. 1월 10일 초안은 내부 메소드 [[Get]]
, [[Put]]
, [[HasProperty]]
, [[Construct]]
, [[Call]]
과 내부 속성 [[Prototype]]
을 정의하였다. 이러한 내부 메소드들은 객체 속성 접근, 프로토타입 상속, 그리고 함수 호출의 시맨틱을 처음으로 형식적으로 표현하는 데 사용되었다. ES1이 완성될 때에는 [[CanPut]]
과 [[Delete]]
내부 메소드가 추가되었다.
첫 번째 초안의 목차에는 네이티브(내장된) ECMAScript 객체들과 브라우저 및 웹 서버 호스팅 환경에서 제공되는 객체들에 대한 섹션이 포함되어 있었다. 하지만 이 섹션들은 1월 10일 초안에서는 비어 있었다. 초안 내에서 'Issue'라고 명시적으로 태그된 항목이 스무 개 있었다. 이들은 부록에서 설명하는 언어 확장 외에 추가적인 것들이었다.
Scott Wiltamuth (note taker) | Microsoft |
Brendan Eich | Netscape |
Shon Katzenberger | Microsoft |
Michael Gardner (1st draft co-editor) | Borland |
Randy Solton (1st draft co-editor) | Borland |
Clayton Lewis | Netscape |
Guy Steele (editor) | Sun |
그림 15. ES1 명세 작업 그룹의 정규 구성원
1월 10일 초안은 1997년 1월 15일에 열린 첫 번째 기술 작업 그룹 회의의 논의 기반으로 사용되었다. 여기서는 여러 중요한 결정들이 내려졌는데 [Wiltamuth 1997a] 다음과 같은 내용을 포함한다.
- 첫 번째 표준은 브라우저나 웹 서버와 같은 호스트 환경에서 제공하는 라이브러리 객체와 함수들에 대한 명세는 제공하지 않는다.
- 현재 언어의 확장은 먼저 완전한 초안 명세가 만들어진 후에 고려한다.
- 쉼표와
?
연산자는 참조값을 전파하지 않는다. 따라서 이들은 할당문의 왼쪽에 쓰일 수 없고 함수 호출에this
값을 제공하지 않는다. - 아스키 코드가 아닌 유니코드 문자는 식별자에 사용하는 것을 허용하지 않는다.
- NUL (U+0000)문자는 문자열 값으로 허용된다.
- 전역 함수와 변수 선언은 enumerable, deletable한 속성을 만든다. 명세에서는 내장 객체의 속성들을 기본적으로 enumerable하지 않고 deletable하지도 않다고 정의한다.
첫번째 작업 그룹 회의에서 해결되지 않은 미해결 이슈는 다중 할당의 평가 순서, 상속된 읽기 전용 속성에 대한 할당의 시맨틱, 1970년 이전의 날짜 값을 어떻게 수용할지 등이 있었다.
작업 그룹(그림 15)은 1997년 4월 중순까지 정기적으로 회의를 가졌다. 그룹은 주요한 문제들과 부차적인 문제들의 목록을 만들고 편집자들이 초안 내용을 작업하고 나면 그것을 검토하는 작업을 했다. 아홉 차례의 작업 회의에 대한 노트가 남아 있다 [Wiltamuth 1997a,b,c,d,e,f,g,h,i]. 작업 그룹 회의 중 일부에 참석한 Richard Gabriel은 회의에서 자주 있었던 개인적인 소통들을 회상했다. Guy Steele는 기능들이 몇몇 엣지케이스에서 어떻게 동작하는지에 대한 질문을 하곤 했다. 때때로 Brendan Eich는 "모르겠다"고 말했고, 때로는 Eich와 Shon Katzenberger가 의심스러워하거나 의견이 달랐다. 그런 경우 그들은 각자의 구현에서 그 테스트 케이스를 시도했다. 만약 각각의 구현에서 같은 동작이 나오면 그것이 명세에 기재된 동작이 되었다. 만약 각 구현 간에 다른 동작이 나오면 그들은 합의에 도달할 때까지 그 문제에 대해 논의했다.
Gardner와 Solton이 작성한 명세 초안에 이어 1997년 2월 27일부터 5월 2일까지 Guy Steele이 작성한 7개의 추가적인 명세 초안이 전체 위원회에 발표되었다. 그리고 작업 그룹 내에서 추가적인 작업 초안이 유통되었다. Ecma 총회를 위한 최종 초안[TC39 1997b]을 제외하면 각 초안은 자세한 문제 해결 로그를 포함하고 있었다 [TC39 1997d].
일부 문제는 Javascript와 그 사용에 장기적인 영향을 미쳤다. 예를 들어 계속해서 논의된 한 가지 주제는 불린 연산자 &&
와 ||
의 short-circuit 평가에 관한 문제였다. &&
와 ||
연산자가 불린으로 형변환 가능한 피연산자를 받았을 때 피연산자 중 하나의 실제 값으로 평가될 것인가("Perl 스타일") 아니면 불린형의 true
아니면 false
값으로 평가될 것인가("Java 스타일")? Brendan Eich는 대부분의 경우 "Perl 스타일" 시맨틱으로 그것을 구현했지만 몇 가지 경우에는 "Java 스타일"의 동작을 하도록 구현했다. Microsoft와 볼랜드는 모든 경우에 "Java 스타일" 시맨틱을 구현했다. 최종 결정은 "Perl 스타일"을 일관되게 적용하는 것이었다.
그 결정은 몇 년 뒤 널리 사용되는 Javascript 용법을 가능하게 만들었다(역주: &&
과 ||
이 피연산자의 실제 값을 반환하는 것을 이용해서 a || b
와 같이 쓰면 a
가 falsy 값이면 b
를 사용하는 등의 용법을 말함). null과 undefined는 불 린 연산자에 의해 false로 형변환되며 모든 Object 참조는 true로 형변환된다. 이런 문법은 객체 속성과 선택적 함수 매개변수에 대한 기본값을 제공하는 그림 16의 용법을 가능하게 했다.
function f( options ) {
options = options || getDefaultOptionsObject () ;
// if an options object was passed , use it .
// otherwise use the default set of options
...
}
ES1
그림 16. ECMAScript 1은 함수 매개변수의 기본값을 설정하는 용법을 가능하게 했다.
Brendan Eich는 ==
연산자가 타입 형변환을 하지 않도록 하는 그의 Javascript 1.2 변경 사항을 포함시키고자 했다고 회상한다. Shon Katzenberger는 그런 변경 사항은 기존의 많은 웹 페이지들을 망가뜨릴 것이므로 너무 늦었다고 성공적으로 반박했다. Eich는 SpiderMonkey의 Javascript 1.3 릴리즈에서 ==
연산자 동작을 원래대로 되돌렸다.
TC39의 세 번째 회의는 1997년 3월 18일부터 19일까지였다. 이는 6월의 Ecma 총회 전 마지막으로 예정된 공식적인 TC39 회의였다. 그 총회에서 Javascript 표준의 첫번째 판본이 수용되고 승인될 거라고 기대되었다. 이 일정에 맞추기 위해 TC39는 세 번째 회의에서 총회에 표준을 회부하는 것에 대한 투표를 해야 했다.
3월 12일 초안 버전 0.12 [TC39 1997a]가 전체 위원회에 배포되었다. 그리고 3월 14일의 작업 그룹 회의에서 논의되었다[TC39 1997f]. 이 초안은 기술적으로 거의 완성되어 있었다. 하지만 Date 객체의 복잡한 정의 부분은 여전히 각 섹션의 제목들만 적혀 있는 상태였다. Shon Katzenberger는 논의와 검토만 거치면 명세에 통합될 수 있는 수준인, 명세급 수준의 완성된 제안서를 가지고 있었다. 문서는 1월 10일 초안 완성 이후 2달 동안 41페이지에서 96페이지로 늘어났다. 초안 0.12는 Date 객체 명세가 없었고 8개의 "Issue" 태그와 6개의 중요한 문제 추적 부록 항목들을 가지고 있었다. 몇십 개의 다른 문제들이 작업 그룹 회의에서 논의되었고 명세에서 다루어져야 했다.
Scott Wiltamuth는 논쟁의 여지가 있는 문제가 남아 있지 않으며 3월 말까지 완성된 초안을 만들 수 있다고 보증했다. 거기에 따라 TC39는 6월에 승인 투표를 하기 위해 Ecma 총회에 초안을 전달하기로 만장일치로 합의했다. 명세 작업 그룹은 명세 작업을 마무리하고 Ecma 사무국 직원과 협력하여 그들의 일정과 형식적인 요구 사항에 맞는 최종 초안을 제작해야 했다. 초안을 완성하는 것은 Wiltamuth가 예상한 것보다 한 달 더 걸렸다. 1997년 5월 2일 최종 초안[TC39 1997b]이 완성되기 전에 3개의 추가적인 중간 초안이 내부적으로 배포되었다. 그리고 5월 5일에 최종 초안이 Ecma 총회 위원들에게 배포되었다. 최종 초안은 Ecma의 문서 관례를 준수하였고, Richard Gabriel이 작성한 Javascript에 대한 비규범적인g 개요를 포함하고 있었다. 1997년 6월 총회는 몇 가지 사소한 편집 변경 사항을 수정한 후 초안을 Ecma 표준 ECMA-262 1판으로 출판하기로 합의했다. 그리고 ISO 패스트트랙 과정에 제출하기로 결정했다. 1997년 9월 10일 편집 변경이 완료되고 TC39에 배포되었다. ECMA-262, 1판은 1997년 9월 16일-17일의 TC39 [1997h] 회의에서 출판을 위해 공개되었다 [Steele 1997].