From 3a6943fb2da860610ccc7d8522e6e10415a47f03 Mon Sep 17 00:00:00 2001 From: huckjoo Date: Thu, 29 Jun 2023 01:02:30 +0900 Subject: [PATCH 1/3] =?UTF-8?q?docs:=20indices=20flag=20=EB=B2=88=EC=97=AD?= =?UTF-8?q?=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ko/proposal-regexp-match-indices.md | 94 +++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/ko/proposal-regexp-match-indices.md diff --git a/src/ko/proposal-regexp-match-indices.md b/src/ko/proposal-regexp-match-indices.md new file mode 100644 index 0000000..86b9e26 --- /dev/null +++ b/src/ko/proposal-regexp-match-indices.md @@ -0,0 +1,94 @@ +# RegExp Match Indices for ECMAScript + +ECMAScript `RegExp` Match indices는 입력 문자열의 시작과 관련하여 캡처된 부분 문자열의 시작 및 종료 인덱스에 대한 추가 정보를 제공합니다. + +폴리필은 [`regexp-match-indices`](https://www.npmjs.com/package/regexp-match-indices) NPM 패키지에서 찾을 수 있습니다. +> 주의: 이 제안서는 "RegExp Match Array Offsets" 라는 이름이었지만, 제안서의 현재 상태를 조금 더 정확하게 표현하기 위해서 이름이 변경되었습니다. + +## 상태 +4단계: 챔피언: Ron Buckton (@rbuckton) +제안의 상세한 상태를 보고 싶다면, 아래의 [TODO](#todo)를 보세요. + +## 제안 동기 +오늘날, ECMAScript `RegExp` 객체는 `exec` 메서드를 호출할 때 일치하는 정보를 제공해줄 수 있습니다. 이 결과는 `Array`이고 일치된 것들의 부분 문자열에 대한 정보를 담고 있고, `input` 문자열에 대한 추가적인 속성과, 매치가 이뤄진 곳의 `index`와, 명명된 캡처 그룹의 부분문자열을 포함하는 `groups` 객체 또한 제공합니다. + +그러나, 이 정보들이 충분하지 않는 고급 시나리오들이 몇몇 존재합니다. 예를 들어 TextMate 언어 구문 하이라이팅에 대한 ECMAScript의 구현은 일치되는 것의 `index`만으로는 부족하고, 독립된 캡처 그룹의 시작과 끝 인덱스가 추가로 필요합니다. + +RegExpBuiltInExec 추상화 작동(그리고 `RegExp.prototype.exec()`, `String.prototype.match` 등의 결과에도)의 추가적인 결과 배열(부분 문자열 배열)에 `indices` 속성을 추가하는 것을 채택하는 것을 제안합니다. 이 속성은 각각의 캡처된 부분 문자열의 시작과 끝 인덱스를 담고 있는 배열 자체일 것입니다. 일치되지 않은 캡처 그룹들은 부분 문자열 배열에서의 응답되는 요소와 비슷한 방식으로 `undefined`가 될 것입니다. 추가로, indices 배열은 각각의 명명된 캡처 그룹의 시작과 끝 인덱스를 포함하는 속성인 `groups`를 가질 것입니다. +> 주의: 성능 이슈로, `indices`는 `d` 플래그가 지정된 경우에만 결과에 추가될 것입니다. + +## 왜 RegExp 플래그로 `d`를 사용하는가? +`indices`에 `d`가 포함되어 있어서 `d`를 선택했습니다. 이 단어는 해당 기능(RegExp의 `lastIndex`, match의 `index`등)의 근본이 되는 명칭입니다. 문자 `i`는 ignore-cases(대소문자 무시)에 이미 사용되고 있고, `n`은 캡처링 vs 비-캡처링 그룹을 다루기 위해 다른 엔진에서 선행되고 있습니다. 이는 `s`가 dot-all을 위해 사용되고 있기 때문에 "sticky" 플래그를 `y`로 사용하는 것과 유사합니다. + +**왜 `d`와 `indices` 대신 `o`와 `offsets`를 사용하지 않나요?** 우리의 목표가 RegExp의 기존 용어(`lastIndex`와 `index`)와 속성의 이름을 일치시키기 위함이기 때문입니다. + +**`d`가 다른 엔진에는 다른 의미를 갖지 않나요?** 맞기도 하고 아니기도 합니다. 소수의 엔진들(Onigmo, Perl, java.util.regex)은 다른 의미의 `d` 플래그를 가지고 있습니다. Onigmo와 Perl은 `d` 플래그를 하위 호환성의 의미(Perl의 문서에는 사용을 권장하지 않는다고 강조되어 있습니다)로 사용하는 반면, java.util.regex는 `d`를 개행 처리에 사용합니다. 46개의 다른 RegExp 엔진에서 지원받는 전체 리스트를 [flags_comparison.md](./flags_comparison.md)에서 찾아볼 수 있습니다. + +## 선행 기술 +* Oniguruma NodeJS bindings: [`captureIndices` property](https://github.com/atom/node-oniguruma#onigscannerfindnextmatchsyncstring-startposition) +* .NET: [`Capture.Index` Property](https://msdn.microsoft.com/en-us/library/system.text.regularexpressions.capture.index(v=vs.110).aspx) +* Java: [`Matcher.start(int)` Method](https://docs.oracle.com/javase/7/docs/api/java/util/regex/Matcher.html#start(int)) + +## 예제[1][] +```js +const re1 = /a+(?z)?/d; + +// indices are relative to start of the input string: +const s1 = "xaaaz"; +const m1 = re1.exec(s1); +m1.indices[0][0] === 1; +m1.indices[0][1] === 5; +s1.slice(...m1.indices[0]) === "aaaz"; + +m1.indices[1][0] === 4; +m1.indices[1][1] === 5; +s1.slice(...m1.indices[1]) === "z"; + +m1.indices.groups["Z"][0] === 4; +m1.indices.groups["Z"][1] === 5; +s1.slice(...m1.indices.groups["Z"]) === "z"; + +// capture groups that are not matched return `undefined`: +const m2 = re1.exec("xaaay"); +m2.indices[1] === undefined; +m2.indices.groups["Z"] === undefined; +``` + +## TODO +The following is a high-level list of tasks to progress through each stage of the [TC39 proposal process](https://tc39.github.io/process-document/): + +### Stage 1 Entrance Criteria + +* [x] Identified a "[champion][Champion]" who will advance the addition. +* [x] [Prose][Prose] outlining the problem or need and the general shape of a solution. +* [x] Illustrative [examples][Examples] of usage. +* [x] High-level [API][API]. + +### Stage 2 Entrance Criteria + +* [x] [Initial specification text][Specification]. +* [ ] ~~[Transpiler support][Transpiler] (_Optional_).~~ + +### Stage 3 Entrance Criteria + +* [x] [Complete specification text][Specification]. +* [x] Designated reviewers have [signed off][Stage3ReviewerSignOff] on the current spec text. +* [x] The ECMAScript editor has [signed off][Stage3EditorSignOff] on the current spec text. + +### Stage 4 Entrance Criteria + +* [x] [Test262](https://github.com/tc39/test262) acceptance tests have been written for mainline usage scenarios and [merged][Test262PullRequest]. +* [x] Two compatible implementations which pass the acceptance tests: + * [x] V8 ([tracking bug](https://bugs.chromium.org/p/v8/issues/detail?id=9548)) — Shipping in Chrome Canary 91 (V8 v9.0.259) + * [x] SpiderMonkey ([tracking bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1519483)) — Shipping in Firefox Nightly 88 + * [x] JavaScriptCore ([tracking bug](https://bugs.webkit.org/show_bug.cgi?id=202475)) — Shipping in Safari Technology Preview 122 + * [x] Engine262 ([PR#1](https://github.com/engine262/engine262/pull/99), [PR#2](https://github.com/engine262/engine262/pull/161)) +* [x] A [pull request][Ecma262PullRequest] has been sent to tc39/ecma262 with the integrated spec text. +* [x] The ECMAScript editor has signed off on the [pull request][Ecma262PullRequest]. + +[1]: #1 +--- + +#### 1 + +[Named Capture Group](https://github.com/11st-corp/tc39-ko/blob/main/src/ko/proposal-regexp-named-groups.md) \ No newline at end of file From 313cab6aeb06fc5a565626faf7503eee1e44f15f Mon Sep 17 00:00:00 2001 From: huckjoo Date: Tue, 4 Jul 2023 00:15:05 +0900 Subject: [PATCH 2/3] =?UTF-8?q?docs:=20=EC=B4=88=EC=95=88=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ko/proposal-class-static-block.md | 53 +++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/ko/proposal-class-static-block.md diff --git a/src/ko/proposal-class-static-block.md b/src/ko/proposal-class-static-block.md new file mode 100644 index 0000000..d2873cc --- /dev/null +++ b/src/ko/proposal-class-static-block.md @@ -0,0 +1,53 @@ +# ECMAScript class static initialization blocks + +클래스 `static` 블럭은 클래스 정의 평가중에 추가적인 정적(static) 초기화를 수행하는 메커니즘을 제공합니다. + +이는 공개(public) 필드에 대한 대체품으로 의도되지 않았습니다. 공개 필드는 정적 분석 도구에 대한 유용한 정보를 제공해주고, 데코레이터를 위한 유효한 대상이 되기 때문입니다. 대신, 기존 사용 사례를 보완하고 해당 제안으로 현재 처리되고있지 않은 새로운 사용 사례를 가능하게 하는 것을 목적으로 합니다. + +## 상태 +단계: 4 +챔피언: Ron Buckton (@rbuckton) +본 제안에 대한 상세한 상태를 보려면 아래 [TODO](#todo)를 살펴보세요. + +## 저자 +- Ron Buckton (@rbuckton) + +## 제안 동기 +정적 필드와 정적 비공개 필드에 대한 현재 제안은 ClassDefinitionEvaluation 을 수행 중에 스태틱 사이드의 필드별 초기화를 수행하는 매커니즘을 제공합니다, 그러나 쉽게 처리되지 않는 몇몇 사례들이 존재합니다. 예를 들어, 상태를 초기화 도중에 평가해야 한다거나(예를 들어 `try..catch`와 같이), 하나의 값에서 두 개의 필드를 세팅해야 한다면 해당 로직을 클래스 정의 바깥에서 수행해야 합니다. + +```js +// without static blocks: +class C { + static x = ...; + static y; + static z; +} + +try { + const obj = doSomethingWith(C.x); + C.y = obj.y + C.z = obj.z; +} +catch { + C.y = ...; + C.z = ...; +} + +// with static blocks: +class C { + static x = ...; + static y; + static z; + static { + try { + const obj = doSomethingWith(this.x); + this.y = obj.y; + this.z = obj.z; + } + catch { + this.y = ...; + this.z = ...; + } + } +} +``` \ No newline at end of file From af7448d13bd2cb18f9dc84632b129bf05bb1cbc8 Mon Sep 17 00:00:00 2001 From: huckjoo Date: Fri, 7 Jul 2023 00:48:20 +0900 Subject: [PATCH 3/3] =?UTF-8?q?docs:=20class-static-block=20=EB=B2=88?= =?UTF-8?q?=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ko/proposal-class-static-block.md | 148 +++++++++++++++++++++++++- 1 file changed, 145 insertions(+), 3 deletions(-) diff --git a/src/ko/proposal-class-static-block.md b/src/ko/proposal-class-static-block.md index d2873cc..67c3dc9 100644 --- a/src/ko/proposal-class-static-block.md +++ b/src/ko/proposal-class-static-block.md @@ -1,6 +1,6 @@ # ECMAScript class static initialization blocks -클래스 `static` 블럭은 클래스 정의 평가중에 추가적인 정적(static) 초기화를 수행하는 메커니즘을 제공합니다. +클래스 `static` 블록은 클래스 정의 평가중에 추가적인 정적(static) 초기화를 수행하는 메커니즘을 제공합니다. 이는 공개(public) 필드에 대한 대체품으로 의도되지 않았습니다. 공개 필드는 정적 분석 도구에 대한 유용한 정보를 제공해주고, 데코레이터를 위한 유효한 대상이 되기 때문입니다. 대신, 기존 사용 사례를 보완하고 해당 제안으로 현재 처리되고있지 않은 새로운 사용 사례를 가능하게 하는 것을 목적으로 합니다. @@ -13,7 +13,7 @@ - Ron Buckton (@rbuckton) ## 제안 동기 -정적 필드와 정적 비공개 필드에 대한 현재 제안은 ClassDefinitionEvaluation 을 수행 중에 스태틱 사이드의 필드별 초기화를 수행하는 매커니즘을 제공합니다, 그러나 쉽게 처리되지 않는 몇몇 사례들이 존재합니다. 예를 들어, 상태를 초기화 도중에 평가해야 한다거나(예를 들어 `try..catch`와 같이), 하나의 값에서 두 개의 필드를 세팅해야 한다면 해당 로직을 클래스 정의 바깥에서 수행해야 합니다. +정적 필드와 정적 비공개 필드에 대한 현재 제안은 ClassDefinitionEvaluation 을 수행 중에 정적 사이드의 필드별 초기화를 수행하는 매커니즘을 제공합니다, 그러나 쉽게 처리되지 않는 몇몇 사례들이 존재합니다. 예를 들어, 상태를 초기화 도중에 평가해야 한다거나(예를 들어 `try..catch`와 같이), 하나의 값에서 두 개의 필드를 세팅해야 한다면 해당 로직을 클래스 정의 바깥에서 수행해야 합니다. ```js // without static blocks: @@ -50,4 +50,146 @@ class C { } } } -``` \ No newline at end of file +``` + +또한, 인스턴스 비공개 필드를 가진 클래스와 같은 범위에서 선언된 다른 클래스나 함수 간에 정보 공유가 필요한 경우도 있습니다. +정적 블록은 현재 클래스 선언의 문맥에서 문장을 평가하는 기회를 제공하며, 비공개 상태(인스턴스-비공개 혹은 정적-비공개)에 대한 특권적인 접근이 가능합니다. + +```js +let getX; + +export class C { + #x + constructor(x) { + this.#x = { data: x }; + } + + static { + // getX has privileged access to #x + getX = (obj) => obj.#x; + } +} + +export function readXData(obj) { + return getX(obj).data; +} +``` + + +## "비공개 선언"과의 관계 +제안서: [https://github.com/tc39/proposal-private-declarations](https://github.com/tc39/proposal-private-declarations) + +비공개 선언 제안도 마찬가지로 두 개의 클래스 간에 특권적인 접근의 문제를 해결하기 위해, 비공개 이름을 클래스 선언에서 벗어나 감싸는 범위의 스코프로 이동시키는 것으로 문제를 해결하려고 합니다. 이 관점에서는 약간의 중복이 있을 수 있지만, 비공개 선언은 다단계 정적 초기화 문제를 해결하지 못하며, 비공개 이름을 외부 스코프에 초기화 목적만을 위해 노출할 가능성이 있습니다. + +```js +// with private declarations +private #z; // exposed purely for post-declaration initialization +class C { + static y; + static outer #z; +} +const obj = ...; +C.y = obj.y; +C.#z = obj.z; + +// with static block +class C { + static y; + static #z; // not exposed outside of class + static { + const obj = ...; + this.y = obj.y; + this.#z = obj.z; + } +} +``` +게다가, 비공기 선언은 read-only 접근이 바람직한 경우에도, 읽기 및 쓰기 접근을 모두 허용하는 공유된 비공개 상태에 비공개 이름을 노출시킵니다. 비공개 선언을 이용하여 이를 해결하려면 추가적인 복잡성이 필요합니다(`static{}`을 사용하더라도 비슷한 비용이 발생합니다). + +```js +// with private declarations +private #zRead; +class C { + #z = ...; // only writable inside of the class + get #zRead() { return this.#z; } // wrapper needed to ensure read-only access +} + +// with static +let zRead; +class C { + #z = ...; // only writable inside of the class + static { zRead = obj => obj.#z; } // callback needed to ensure read-only access +} +``` + +그러나, 장기적으로는 두 제안이 함께 작동하는 것을 방해하는 요소는 없습니다. +```js +private #shared; +class C { + static outer #shared; + static #local; + static { + const obj = ...; + this.#shared = obj.shared; + this.#local = obj.local; + } +} +class D { + method() { + C.#shared; // ok + C.#local; // no access + } +} +``` + +## 선행 기술 +- C#: [Static Constructors](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors) +- Java: [Static Initializers](https://docs.oracle.com/javase/specs/jls/se10/html/jls-8.html#jls-8.7) + +## 구문 +```js +class C { + static { + // statements + } +} +``` + +## 의미론 +- `static {}` 초기화 블록은 새로운 lexical 스코프를 생성합니다.(예를 들어 `var`, `function`, 블록 스코프 선언은 `static {}` 초기화 블록에 지역적으로 적용됩니다. 이 lexical 스코프는 클래스 본문의 lexical 스코프 안에 중첩되어 있습니다.(클래스의 비공개 상태의 인스턴스에 대한 특권적인 접근을 보장합니다.)) +- 클래스 본문에서는 여러 개의 `static {}` 초기화 블록을 가질 수 있습니다. +- `static {}` 초기화 블록은 정적 필드 초기화와 교차하여 문서 순서대로 평가됩니다. +- `static {}` 초기화 블록은 데코레이터를 가질 수 없습니다.(클래스 자체에 데코레이터를 적용해야 함) +- 평가될 때, `static {}` 초기화 블록의 `this` 수신자는 클래스의 생성자 객체입니다. (정적 필드 초기화와 동일) +- `static {}` 초기화 블록 내부에서 `arguments`를 참조하는 것은 문법 오류입니다. +- `static {}` 초기화 블록 내부에서 SuperCall(즉, `super()`)을 포함하는 것은 문법 오류입니다. +- `static {}` 초기화 블록은 기반 클래스의 정적 멤버에 접근하거나 호출하기 위한 수단으로 SuperProperty 참조를 포함할 수 있습니다. 이러한 기반 클래스는 `static {}` 초기화 블록을 포함한 파생 클래스에 의해 재정의될 수 있습니다. +- `static {}` 초기화 블록은 디버거 및 예외 추적에서 독립적인 스택 프레임으로 표시되어야 합니다. + +## 예시 +```js +// "friend" access (same module) +let A, B; +{ + let friendA; + + A = class A { + #x; + + static { + friendA = { + getX(obj) { return obj.#x }, + setX(obj, value) { obj.#x = value } + }; + } + }; + + B = class B { + constructor(a) { + const x = friendA.getX(a); // ok + friendA.setX(a, x); // ok + } + }; +} +``` +## 참조 +- [Stage 0 Presentation](https://docs.google.com/presentation/d/1TLFrhKMW2UHlHIcjKN02cEJsSq4HL7odS6TE6M-OGYg/edit#slide=id.p) \ No newline at end of file