7 | title: Proposal Title Goes Here
8 | stage: -1
9 | contributors: Your Name(s) Here
10 |
11 |
12 |
13 |
This is an emu-clause
14 |
This is an algorithm:
15 |
16 | 1. Let _proposal_ be *undefined*.
17 | 1. If IsAccepted(_proposal_),
18 | 1. Let _stage_ be *0*.
19 | 1. Else,
20 | 1. Let _stage_ be *-1*.
21 | 1. Return ? ToString(_proposal_).
22 |
23 |
24 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "proposal-regexp-features",
3 | "version": "0.0.0",
4 | "private": true,
5 | "description": "Proposal to investigate additional language features for ECMAScript Regular Expressions",
6 | "homepage": "https://github.com/rbuckton/proposal-regexp-features#readme",
7 | "author": {
8 | "name": "Ron Buckton",
9 | "email": "ron.buckton@microsoft.com"
10 | },
11 | "keywords": [
12 | "javascript",
13 | "ecmascript"
14 | ],
15 | "scripts": {
16 | "build": "gulp build",
17 | "start": "gulp start"
18 | },
19 | "license": "MIT",
20 | "devDependencies": {
21 | "del": "^5.1.0",
22 | "ecmarkup": "^8.1.0",
23 | "gulp": "^4.0.2",
24 | "gulp-emu": "^2.0.0",
25 | "gulp-live-server": "0.0.31"
26 | },
27 | "repository": {
28 | "type": "git",
29 | "url": "git+https://github.com/rbuckton/proposal-regexp-features.git"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | const del = require("del");
2 | const path = require("path");
3 | const gulp = require("gulp");
4 | const emu = require("gulp-emu");
5 | const gls = require("gulp-live-server");
6 |
7 | gulp.task("clean", () => del("docs/**/*"));
8 |
9 | gulp.task("build", () => gulp
10 | .src(["spec/index.html"])
11 | .pipe(emu({ ecma262Biblio: false, js: true, css: true }))
12 | .pipe(gulp.dest("docs")));
13 |
14 | gulp.task("watch", () => gulp
15 | .watch(["spec/**/*"], gulp.task("build")));
16 |
17 | gulp.task("start", gulp.parallel(gulp.task("watch"), () => {
18 | const server = gls.static("docs", 8080);
19 | const promise = server.start();
20 | (/** @type {import("chokidar").FSWatcher}*/(gulp.watch(["docs/**/*"])))
21 | .on("change", file => {
22 | server.notify({ path: path.resolve(file) });
23 | });
24 | return promise;
25 | }));
26 |
27 | gulp.task("default", gulp.task("build"));
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 ECMA TC39 and contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # ECMAScript Regular Expression Language Features
3 |
4 | This seeks to investigate and introduce new features to the ECMAScript `RegExp` object based on features available commonly in other languages.
5 |
6 |
7 |
8 |
9 | ## Status
10 |
11 | **Stage:** 0
12 | **Champion:** Ron Buckton (@rbuckton)
13 |
14 | _For detailed status of this proposal see [TODO](#todo), below._
15 |
16 |
17 |
18 | ## Authors
19 |
20 | * Ron Buckton ([@rbuckton](https://github.com/rbuckton))
21 |
22 |
23 |
24 | # Motivations
25 |
26 | ECMAScript regular expressions have slowly improved over the years to adopt new functionality commonly present in other languages, including:
27 |
28 | - Unicode Support
29 | - Named Capture Groups
30 | - Match Indices
31 |
32 | However, a large majority of other languages and libraries have a common set of features that ECMAScript regular expressions currently lack.
33 | Some of these features improve performance in degenerative cases such as backtracking in complex patterns. Some of these features introduce
34 | new tools for developers to write more powerful regular expressions.
35 |
36 | As a result, ECMAScript developers wishing to leverage these capabilities are left with few options, relying on native bindings to third-party
37 | libraries in environments such as NodeJS, or server-side evaluation.
38 |
39 | There are numerous applications for extending the ECMAScript regular expression feature set, including:
40 |
41 | - In-browser support for TextMate grammars for web based editors/IDEs.
42 | - Improved performance for expressions through possessive quantifiers and backtracking control.
43 | - RegExp-based parsers that can support balanced brackets/parens.
44 | - Documenting complex patterns *in the pattern itself*.
45 | - Improved readability through the use of multi-line patterns and insignificant whitespace.
46 |
47 |
48 |
49 |
50 |
56 |
57 |
58 |
59 | # Syntax
60 |
61 | This proposal seeks to investiage multiple additions to the ECMAScript regular expression syntax based on features commonly available in
62 | other languages and engines. This work is based on the research at https://rbuckton.github.io/regexp-features/, which is an ongoing effort
63 | to document the commonalities and differences of various features in popular regular expression engines. This proposal does not seek to
64 | implement *all* of the proposed syntax, but to investigate each feature to determine its applicability to ECMAScript. Where possible,
65 | we will indicate whether the syntax described should be considered *definitive* (i.e., the specific syntax is not subject to change should
66 | the feature be adopted), or *proposed* (i.e., the specific syntax is open for debate).
67 |
68 | Definitive syntax is that which is generally-consistent with all engines that implement the functionality,
69 | such that a change to the syntax would have a net-negative effect when considering compatibility with other engines (such as would be the
70 | case with TextMate grammars, patterns commonly used in documentation to describe a valid input, etc.).
71 |
72 | Proposed syntax is that which is inconsistent between the various engines that implement similar
73 | functionality, such that a change to the syntax to fit ECMAScript requirements would not likely be a compatiblity concern.
74 |
75 | ## Flags
76 |
77 | ### Explicit capture mode (`n`)
78 |
79 | **Status:** [Definitive][]
80 |
81 | **Prior Art:** Perl, PCRE, .NET ([feature comparison](https://rbuckton.github.io/regexp-features/features/flags.html))
82 |
83 | The explicit capture mode (`n`) flag affects capturing behavior, such that normal capture groups (i.e., `()`) are treated as non-capturing groups. Only named capture groups are returned.
84 |
85 | > NOTE: The `n`-mode flag can be used inside of a [Modifier](#modifiers).
86 |
87 | #### API
88 |
89 | - `RegExp.prototype.explicitCapture` (Boolean) — Indicates whether the `n`-mode flag is set.
90 |
91 | ### Extended mode (`x`)
92 |
93 | **Status:** [Definitive][]
94 |
95 | **Prior Art:** Perl, PCRE, Boost.Regex, .NET, Oniguruma, Hyperscan, ICU, Glib/GRegex ([feature comparison](https://rbuckton.github.io/regexp-features/features/flags.html))
96 |
97 | The extended mode (`x`) flag treats unescaped whitespace characters as insignificant, allowing for multi-line regular expressions. It also enables [Line Comments](#line-comments).
98 |
99 | > NOTE: The `x`-mode flag can be used inside of a [Modifier](#modifiers)
100 |
101 | > NOTE: While the `x`-mode flag can be used in a _RegularExpressionLiteral_, it does not permit the use of _LineTerminator_ in _RegularExpressonLiteral_. For multi-line
102 | > regular expressions you would need to use the `RegExp` constructor.
103 |
104 | > NOTE: Perl's original `x`-mode treated whitespace as insignificant anywhere within a pattern *except* for within character classes. Perl v5.26 introduced the `xx` flag which
105 | > also ignores non-escaped SPACE and TAB characters. Should we chose to adopt the `x`-mode flag, we could opt to treat it as Perl's `xx` mode at the outset.
106 |
107 | #### API
108 |
109 | - `RegExp.prototype.extended` (Boolean) — Indicates the `x`-mode flag is set.
110 |
111 | ## Modifiers
112 |
113 | **Status:** [Definitive][]
114 |
115 | **Prior Art:** Perl, PCRE, Boost.Regex, .NET, Oniguruma, Hyperscan, ICU, Glib/GRegex ([feature comparison](https://rbuckton.github.io/regexp-features/features/modifiers.html))
116 |
117 | Modifiers allow you to change the currently active RegExp flags within a subexpression.
118 |
119 | - `(?imnsux-imnsux)` — Sets or unsets (using `-`) the specified RegExp flags starting at the current position until the next closing `)` or the end of the pattern.
120 | - `(?imnsux-imnsux:subexpression)` — Sets or unsets (using `-`) the specified RegExp flags for the subexpression.
121 |
122 | > NOTE: Certain flags cannot be modified mid-expression. These currently include `g` (global), `y` (sticky), and `d` (hasIndices).
123 |
124 | > NOTE: This has no conflicts with existing syntax, as ECMAScript currently produces an error for this syntax in both `u` and non-`u` modes.
125 |
126 | #### Example
127 |
128 | ```js
129 | const re1 = /^(?i)[a-z](?-i)[a-z]$/;
130 | re1.test("ab"); // true
131 | re1.test("Ab"); // true
132 | re1.test("aB"); // false
133 |
134 | const re2 = /^(?i:[a-z](?-i:[a-z]))$/;
135 | re2.test("ab"); // true
136 | re2.test("Ab"); // true
137 | re2.test("aB"); // false
138 | ```
139 |
140 | ## Comments
141 |
142 | **Status:** [Definitive][]
143 |
144 | **Prior Art:** Perl, PCRE, Boost.Regex, .NET, Oniguruma, Hyperscan, ICU, Glib/GRegex ([feature comparison](https://rbuckton.github.io/regexp-features/features/comments.html))
145 |
146 | A comment is a sequence of characters that is ignored by pattern matching and can be used to document a pattern.
147 |
148 | - `(?#comment)` — The entire expression is removed from the pattern. The text of *comment* may not contain other `(` or `)` characters.
149 |
150 | > NOTE: This has no conflicts with existing syntax, as ECMAScript currently produces an error for this syntax in both `u` and non-`u` modes.
151 |
152 | #### Example
153 |
154 | ```js
155 | const re = /foo(?#comment)bar/;
156 | re.test("foobar"); // true
157 | ```
158 |
159 | ## Line Comments
160 |
161 | **Status:** [Definitive][]
162 |
163 | **Prior Art:** Perl, PCRE, .NET, ICU, Glib/GRegex ([feature comparison](https://rbuckton.github.io/regexp-features/features/line-comments.html))
164 |
165 | A Line Comment is a sequence of characters starting with `#` and ending with `\n` (or the end of the pattern) that is ignored by pattern matching and can be used to document a pattern.
166 |
167 | - `# comment` — A line comment in a multi-line RegExp
168 |
169 | > NOTE: Requires the `x`-mode [flag](#extended-mode-x).
170 |
171 | > NOTE: Inside of `x`-mode, the `#` character must be escaped (using `\#`) outside of a character class.
172 |
173 | #### Example
174 |
175 | ```js
176 | const re = new RegExp(String.raw`
177 | # match ASCII alpha-numerics
178 | [a-zA-Z0-9]
179 | `, "x");
180 | ```
181 |
182 | ## Buffer Boundaries
183 |
184 | **Status:** [Definitive][]
185 |
186 | **Prior Art:** Perl, PCRE, Boost.Regex, .NET, Oniguruma, Hyperscan, ICU, Glib/GRegex ([feature comparison](https://rbuckton.github.io/regexp-features/features/buffer-boundaries.html))
187 |
188 | Buffer boundaries are similar to the `^` and `$` anchors, except that they are not affected by the `m` (multiline) flag:
189 |
190 | - `\A` — Matches the start of the input.
191 | - `\z` — Matches the end of the input.
192 | - `\Z` — A zero-width assertion consisting of an optional newline at the end of the buffer. Equivalent to (?=\n?\z).
193 |
194 | > NOTE: Requires the `u` flag, as `\A`, `\z`, and `\Z` are currently just escapes for `A`, `z` and `Z` without the `u` flag.
195 |
196 | > NOTE: Not supported inside of a character class.
197 |
198 |
199 | ## Line Endings Escape
200 |
201 | **Status:** [Definitive][]
202 |
203 | **Prior Art:** Perl, PCRE, Boost.Regex, Oniguruma, ICU, Glib/GRegex ([feature comparison](https://rbuckton.github.io/regexp-features/features/line-endings-escape.html))
204 |
205 | - `\R` — Matches any [line ending character sequence per UTS#18](https://unicode.org/reports/tr18/#Line_Boundaries). Equivalent to: `(?>\r\n?|[\x0A-\x0C\x85\u{2028}\u{2029}])` (see [Atomic Groups](#atomic-groups))
206 |
207 | > NOTE: Requires the `u` flag, as `\R` is currently just an escape for `R` without the `u` flag.
208 |
209 | > NOTE: Not supported inside of a character class.
210 |
211 | ## Possessive Quantifiers
212 |
213 | **Status:** [Definitive][]
214 |
215 | **Prior Art:** Perl, PCRE, Boost.Regex, Oniguruma, ICU, Glib/GRegex ([feature comparison](https://rbuckton.github.io/regexp-features/features/possessive-quantifiers.html))
216 |
217 | Possessive quantifiers are like normal (a.k.a. "greedy") quantifiers, but do not backtrack if the rest of the pattern to the right fails to match. Possessive quantifiers are often used as a performance tweak to avoid expensive backtracking in a complex pattern.
218 |
219 | - `*+` — Match zero or more instances of the preceding atom without backtracking.
220 | - `++` — Match one or more instances of the preceding atom without backtracking.
221 | - `?+` — Match zero or one instances of the preceding atom without backtracking.
222 | - `{n,}+` — Where _n_ is an integer. Matches the preceding atom at-least _n_ times without backtracking.
223 | - `{n,m}+` — Where _n_ and _m_ are integers, and _m_ >= _n_. Matches the preceding atom at-least _n_ times and at-most _m_ times without backtracking.
224 |
225 | > NOTE: This has no conflicts with existing syntax, as ECMAScript currently produces an error for this syntax in both `u` and non-`u` modes.
226 |
227 | ## Atomic Groups
228 |
229 | **Status:** [Definitive][]
230 |
231 | **Prior Art:** Perl, PCRE, Boost.Regex, .NET, Oniguruma, ICU, Glib/GRegex ([feature comparison](https://rbuckton.github.io/regexp-features/features/non-backtracking-expressions.html))
232 |
233 | An Atomic Group is a non-backtracking expression which is matched independent of neighboring patterns, and will not backtrack in the event of a failed match. This is often used to improve performance.
234 |
235 | - `(?>pattern)` — Matches the provided pattern, but no backtracking is performed if the match fails.
236 |
237 | > NOTE: This has no conflicts with existing syntax, as ECMAScript currently produces an error for this syntax in both `u` and non-`u` modes.
238 |
239 | #### Example
240 |
241 | ```js
242 | // NOTE: x-mode flag used to illustrate difference
243 | // without atomic groups:
244 | const re1 = /\(( [^()]+ | \([^()]*\))+ \)/x;
245 | re1.test("((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); // can take several seconds to fail
246 |
247 | // with atomic groups
248 | const re2 = /\(( (?> [^()]+ ) | \([^()]*\))+ \)/x;
249 | re2.test("((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); // significantly faster as less backtracking is involved
250 | ```
251 |
252 | ## Conditional Expressions
253 |
254 | **Status:** [Definitive][]/[Proposed][] (depending on condition, see below)
255 |
256 | **Prior Art:** Perl, PCRE, Boost.Regex, .NET, Oniguruma, Glib/GRegex ([feature comparison](https://rbuckton.github.io/regexp-features/features/conditional-expressions.html))
257 |
258 | A Conditional Expression checks a condition and evaluates its first alternative if the condition is true; otherwise, it evaluates its second alternative.
259 |
260 | - `(?(condition)yes-pattern|no-pattern)` — Matches yes-pattern if condition is true; otherwise, matches no-pattern.
261 | - `(?(condition)yes-pattern)` — Matches yes-pattern if condition is true; otherwise, matches the empty string.
262 |
263 | > NOTE: This has no conflicts with existing syntax, as ECMAScript currently produces an error for this syntax in both `u` and non-`u` modes.
264 |
265 | ### Conditions
266 |
267 | The following conditions are proposed:
268 |
269 | - `(?=test-pattern)` — Evaluates to **true** if a positive lookahead for test-pattern matches; Otherwise, evaluates to **false**.
270 | - **Status**: [Definitive][]
271 | - `(?<=test-pattern)` — Evaluates to **true** if a positive lookbehind for test-pattern matches; Otherwise, evaluates to **false**.
272 | - **Status**: [Proposed][] (backtracking not supported in all engines)
273 | - `(?!test-pattern)` — Evaluates to **true** if a negative lookahead for test-pattern matches; Otherwise, evaluates to **false**.
274 | - **Status**: [Definitive][]
275 | - `(?)` — Evaluates to **true** if the named capture group with the provided _name_ was successfully matched; Otherwise, evaluates to **false**.
280 | - **Status**: [Definitive][]
281 | - `('name')` — Evaluates to **true** if the named capture group with the provided _name_ was successfully matched; Otherwise, evaluates to **false**.
282 | - **Status**: [Definitive][]
283 | - `(R)` — Evaluates to **true** if inside a recursive expression; Otherwise, evaluates to **false**.
284 | - **Status**: [Proposed][] ([recursion](#recursion) not supported in all engines)
285 | - `(Rn)` — Evaluates to **true** if inside a recursive expression for the capture group at offset n; Otherwise, evaluates to **false**.
286 | - **Status**: [Proposed][] ([recursion](#recursion) not supported in all engines)
287 | - `(R&name)` — Evaluates to **true** if inside a recursive expression for the named capture group with the provided name; Otherwise, evaluates to **false**.
288 | - **Status**: [Proposed][] ([recursion](#recursion) not supported in all engines)
289 | - `(DEFINE)` — Always evaluates to **false**. This allows you to define Subroutines.
290 | - **Status**: [Proposed][] ([subroutines](#subroutines) not supported in all engines)
291 |
292 | #### Example
293 |
294 | ```js
295 | // conditional using lookahead:
296 | const re1 = /^(?(?=\{)\{[0-9a-f]+\}|[0-9a-f]{4})$/
297 | re1.test("0000"); // true
298 | re1.test("{0}"); // true
299 | re1.test("{00000000}"); // true
300 |
301 | // match optional brackets
302 | const re2 = /(?\[)?(?[^\]]+)(?()\]))/;
303 | re1.test("abc"); // true
304 | re1.test("[abc]"); // true
305 | re1.test("[abc"); // false
306 | ```
307 |
308 | ## Subroutines
309 |
310 | **Status:** [Proposed][] (some engines use differing syntax)
311 |
312 | **Prior Art:** Perl, PCRE, Boost.Regex, Oniguruma, Glib/GRegex ([feature comparison](https://rbuckton.github.io/regexp-features/features/subroutines.html))
313 |
314 | A Subroutine is a pre-defined capture group or named capture group that can be reused in multiple places within the pattern to re-evaluate the subexpression from the referenced group.
315 |
316 | - `(?n)` — Where _n_ is an integer >= 1. Evaluates the capture group whose offset is _n_.
317 | - `(?-n)` — Where _n_ is an integer >= 1. Evaluates the capture group whose offset is the _n_th capture group declared to the left of the current atom.
318 | - `(?+n)` — Where _n_ is an integer >= 1. Evaluates the capture group whose offset is the _n_th capture group declared to the right of the current atom.
319 | - `(?&name)` — Evaluates the named capture group with the provided name.
320 |
321 | > NOTE: Subroutines also allow [Recursion](#recursion).
322 |
323 | > NOTE: This has no conflicts with existing syntax, as ECMAScript currently produces an error for this syntax in both `u` and non-`u` modes.
324 |
325 | #### Example
326 |
327 | ```js
328 | const iso8601DateRegExp = new RegExp(String.raw`
329 | (?(DEFINE)
330 | (?\d{4}|[+-]\d{5,})
331 | (?0[1-9]|1[0-2])
332 | (?0[1-9]|2[0-9]|3[01])
333 | )
334 | (?(?&Year)-(?&Month)-(?&Day)|(?&Year)(?&Month)(?&Day))
335 | `, "x");
336 | ```
337 |
338 | ## Recursion
339 |
340 | **Status:** [Proposed][] (some engines use differing syntax)
341 |
342 | **Prior Art:** Perl, PCRE, Boost.Regex, Oniguruma, Glib/GRegex ([feature comparison](https://rbuckton.github.io/regexp-features/features/recursion.html))
343 |
344 | A Recursive Expression provides a mechanism for re-evaluating a capture group inside of itself, to handle cases such as matching balanced parenthesis or brackets, etc.
345 |
346 | - `(?R)`, `(?0)` — Reevaluates the entire pattern starting at the current position.
347 |
348 | > NOTE: This has no conflicts with existing syntax, as ECMAScript currently produces an error for this syntax in both `u` and non-`u` modes.
349 |
350 |
351 |
352 |
353 |
357 |
358 |
359 |
360 |
361 |
365 |
366 |
367 |
368 |
372 |
373 |
374 |
375 |
384 |
385 |
386 |
387 | # References
388 |
389 | - [Regular Expression Feature Comparison](https://rbuckton.github.io/regexp-features/)
390 |
391 |
392 |
393 |
394 |
401 |
402 |
403 |
404 | # TODO
405 |
406 | 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/):
407 |
408 | ### Stage 1 Entrance Criteria
409 |
410 | * [x] Identified a "[champion][Champion]" who will advance the addition.
411 | * [ ] [Prose][Prose] outlining the problem or need and the general shape of a solution.
412 | * [x] Illustrative [examples][Examples] of usage.
413 | * [x] High-level [API][API].
414 |
415 | ### Stage 2 Entrance Criteria
416 |
417 | * [ ] [Initial specification text][Specification].
418 | * [ ] [Transpiler support][Transpiler] (_Optional_).
419 |
420 | ### Stage 3 Entrance Criteria
421 |
422 | * [ ] [Complete specification text][Specification].
423 | * [ ] Designated reviewers have [signed off][Stage3ReviewerSignOff] on the current spec text.
424 | * [ ] The ECMAScript editor has [signed off][Stage3EditorSignOff] on the current spec text.
425 |
426 | ### Stage 4 Entrance Criteria
427 |
428 | * [ ] [Test262](https://github.com/tc39/test262) acceptance tests have been written for mainline usage scenarios and [merged][Test262PullRequest].
429 | * [ ] Two compatible implementations which pass the acceptance tests:
430 | * [ ] [_Pending_][Implementation1]
431 | * [ ] [_Pending_][Implementation2]
432 | * [ ] A [pull request][Ecma262PullRequest] has been sent to tc39/ecma262 with the integrated spec text.
433 | * [ ] The ECMAScript editor has signed off on the [pull request][Ecma262PullRequest].
434 |
435 |
436 | [Process]: https://tc39.github.io/process-document/
437 | [Proposals]: https://github.com/tc39/proposals/
438 | [Grammarkdown]: http://github.com/rbuckton/grammarkdown#readme
439 | [Champion]: #status
440 | [Prose]: #motivations
441 | [Examples]: #examples
442 | [API]: #api
443 | [Specification]: #todo
444 | [Transpiler]: #todo
445 | [Stage3ReviewerSignOff]: #todo
446 | [Stage3EditorSignOff]: #todo
447 | [Test262PullRequest]: #todo
448 | [Implementation1]: #todo
449 | [Implementation2]: #todo
450 | [Ecma262PullRequest]: #todo
451 | [Definitive]: #definitive-syntax
452 | [Proposed]: #proposed-syntax
453 |
--------------------------------------------------------------------------------