Skip to content

Commit e0a7f3c

Browse files
committed
Add blog post on new language features
1 parent 9e0886d commit e0a7f3c

File tree

1 file changed

+197
-0
lines changed

1 file changed

+197
-0
lines changed

pages/blog/new-lang-features.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
{
2+
"template": "blog",
3+
"blog": true,
4+
"title": "A Formal Commitment to New Language Features",
5+
"author": "Mike Pennisi",
6+
"date": "2015-07-07",
7+
"url": "/blog/new-lang-features"
8+
}
9+
10+
In recent months, JSHint has been receiving requests to support [proposed
11+
JavaScript language features](https://github.com/tc39/ecma262) like
12+
[`async`/`await`](https://github.com/tc39/ecmascript-asyncawait), [method
13+
decorators](https://github.com/wycats/javascript-decorators), and [class
14+
property declarations](https://gist.github.com/jeffmo/054df782c05639da2adb)
15+
[[1](#ref-1)]. The JSHint team has turned down each request, even after the
16+
release of [ES2015](http://www.ecma-international.org/ecma-262/6.0/). This has
17+
not been easy; as open source project maintainers, nothing gives us more
18+
pleasure than to write code in benefit of our users. We've tried to explain our
19+
motivations in an ad-hoc way, but it's always come off as a bit haphazard. We'd
20+
like to take some time to more thoroughly describe our thought process.
21+
22+
The long and short of it is: JSHint will require all language extension
23+
proposals to be at "Stage 2" of [TC-39's standardization
24+
process](https://docs.google.com/document/d/1QbEE0BsO4lvl7NFTn5WXWeiEIBfaVUF7Dk0hpPpPDzU/edit?pli=1)
25+
before parsing and linting them.
26+
27+
## Why so defensive?
28+
29+
Projects like [Traceur](https://github.com/google/traceur-compiler) and
30+
[Babel](http://babeljs.io/) have become very popular through progressive
31+
implementation of the latest features and proposals. It's fair to question why
32+
JSHint should be any different.
33+
34+
First off, **it's difficult for the project maintainers**. This is not really a
35+
defensible motivation; we only offer it in the interest of full disclosure.
36+
Over the years, JSHint has grown from [JSLint](http://jslint.com/) thanks to
37+
the efforts of hundreds of contributors. This has been key to its success, but
38+
it has also contributed to a fair amount of technical debt. Extending the
39+
parser requires a fair amount of study, and even then, it isn't always clear
40+
how to do this cleanly.
41+
42+
The project has tried to be progressive about new syntax in the past
43+
[[2](#ref-2)], and this has often contributed to technical debt. For instance,
44+
JSHint continues to
45+
([grudgingly](https://github.com/jshint/jshint/pull/2519#issuecomment-118409190))
46+
maintain [a `moz` option for Mozilla-specific
47+
extensions](https://github.com/jshint/jshint/blob/e32e17b97289e4bb5a53116ffc3a979356792088/src/options.js#L466-L476),
48+
and the current `esnext` option includes non-standard array comprehensions. (By
49+
the way: now that ES2015 is released, that name describes a non-existent
50+
specification draft.)
51+
52+
[A plugin system](https://github.com/jshint/jshint/issues/2079) is one possible
53+
way to address this, but that will require a large effort involving careful
54+
design, spanning refactoring, and a long-term commitment to implementation
55+
details.
56+
57+
More importantly, **it's hazardous for developers**. Inconsistencies within
58+
toolchains will gate developers on the lowest common denominator. Imagine the
59+
day that your transpiler supports draft 17 but JSHint has moved to draft 18.
60+
Even if you're not struggling with coordination issues between parsers, the
61+
release cycle for a "progressive" parser would leave most application
62+
developers behind. Projects would frequently rely on outdated release channels
63+
that no longer received bug fixes or new features.
64+
65+
[JSHint was born out of a reluctance to make decisions on behalf of the
66+
user](https://medium.com/@valueof/why-i-forked-jslint-to-jshint-73a72fd3612),
67+
so while we think the above considerations should be made clear to JSHint's
68+
users, we haven't made this decision based on them.
69+
70+
We also believe **it's harmful for the ecosystem**. Empowering developers to
71+
write non-standard code can have long-term effects on the open source
72+
ecosystem. Code has a tendency to live longer than we expect, but it isn't
73+
always maintained throughout its lifetime. We all look forward to the day that
74+
features like method decorators are standard and widely-supported. Prior to
75+
that, it's important to remember that the code we write with experimental
76+
language features is itself non-standard. It will be frustrating if, in 2
77+
years, you are reviewing older code that seems to use "standard" function
78+
decorators but that in reality depends on the syntax and semantics of "revision
79+
12" of the function decorator proposal. The differences may be subtle, and you
80+
will be forced to research the behavior of this not-quite-JavaScript before you
81+
can contribute to the project.
82+
83+
Finally, **it's unhealthy for the language**. TC39 does not operate from an
84+
ivory tower. They recognize practical considerations of patterns in existing
85+
code. Look no further than [Annex
86+
B](http://www.ecma-international.org/ecma-262/6.0/#sec-additional-ecmascript-features-for-web-browsers)
87+
for proof of that. Sometimes, that is a good thing. [The Promises/A+
88+
spec](https://promisesaplus.com/) offered a clear way forward when Promises
89+
were first considered for inclusion in ES2015. Sometimes, this is a bad thing.
90+
It's the reason why we expect
91+
[`Array.prototype.includes`](https://github.com/tc39/Array.prototype.includes/)
92+
instead of
93+
[`Array.prototype.contains`](https://esdiscuss.org/topic/having-a-non-enumerable-array-prototype-contains-may-not-be-web-compatible).
94+
The proliferation of production code can have [a solidifying
95+
effect](https://medium.com/@morrissinger/the-rise-of-the-bully-pulpit-in-the-evolution-of-javascript-94fb394d3b69)
96+
on new features. To the extent that JSHint is a channel through which new
97+
JavaScript flows (a minuscule one to be sure), we want to cooperate with the
98+
design process.
99+
100+
## So why stage 2?
101+
102+
Stage 2 seems specifically designed for our position in the ecosystem.
103+
104+
It's not too early. Features in this stage have a formal definition (so we have
105+
a consistent and complete set of instructions to build from). These features
106+
are also relatively stable, so JSHint has a chance to keep up with the latest
107+
draft modifications.
108+
109+
It's also not too late. The design process can still benefit from the
110+
experience of developers applying a given pattern to their code. The process
111+
document defines "incremental" changes expected for Stage 2 proposals, and only
112+
recommends "experimental" implementations. You might say, "[these features seem
113+
stable enough](https://bugzilla.mozilla.org/show_bug.cgi?id=258974#c22)", but
114+
the truth is, JSHint was dealing with non-trivial modifications to ES2015 from
115+
the moment we implemented them until as late as May of this year [[3](#ref-3)].
116+
So it's worth noting that JSHint is *still* taking some risk here.
117+
118+
We think there's tremendous value in experimentation at earlier stages in the
119+
process. We also feel that research should be conducted in non-production
120+
settings in order to avoid the more fundamental problems discussed above.
121+
Early-stage experiments have less to gain from automated code analysis both
122+
because of their limited scope and because their syntax is already verified by
123+
a "transpiler". In these contexts, linting has much more limited relevance.
124+
125+
## Moving forward
126+
127+
Here's the practical effect of all that talk:
128+
129+
- JSHint 3 will not expose an `esnext` option; it will instead support
130+
`esversion: 6`.
131+
- JSHint will continue to support the `moz` option, and it will be the only
132+
setting that enables array comprehension parsing.
133+
- JSHint will *not* expose an `esversion: 7` option until that specification is
134+
finalized by ECMA.
135+
- JSHint will support for stage-2-and-above proposals under the `experimental`
136+
configuration namespace. These features will be clearly documented as subject
137+
to breaking changes between major releases.
138+
139+
This policy means denying first-class support for non-standard and early
140+
proposal features. JSHint will continue to support `ignore` directives as a
141+
coarse-grained mechanism for operating on non-standard and early-proposal
142+
features, but we know [other linting tools go much farther than
143+
that](https://github.com/babel/babel-eslint). We're motivated by our
144+
responsibility to developers but also to the open source ecosystem and to the
145+
standards process itself. We hope JSHint's usership continues to enjoy the tool
146+
because they share these same values.
147+
148+
---
149+
150+
<span id="ref-1">
151+
[1] Requests for proposed language features:
152+
153+
- [gh-1977 WIP: Async/await](https://github.com/jshint/jshint/pull/1977)
154+
- [gh-1979 Added optional asyncawait support on top of
155+
esnext](https://github.com/jshint/jshint/pull/1979)
156+
- [gh-2077 AsyncAwait plugin](https://github.com/jshint/jshint/pull/2077)
157+
- [gh-2297 Please add support for ES7 method
158+
decorators](https://github.com/jshint/jshint/issues/2297)
159+
- [gh-2304 ES7 Class Properties throws 'Unexpected token
160+
='](https://github.com/jshint/jshint/issues/2304)
161+
- [gh-2309 class property initializers
162+
proposal](https://github.com/jshint/jshint/issues/2309)
163+
- [gh-2310 Support for ES7
164+
decorators?](https://github.com/jshint/jshint/issues/2310)
165+
- [gh-2504 ES7: async and await](https://github.com/jshint/jshint/issues/2504)
166+
167+
</span>
168+
169+
<span id="ref-2">
170+
[2] Introduction of ES6 features
171+
172+
- [gh-971 Arrow functions](https://github.com/jshint/jshint/pull/971) (13.03.28)
173+
- [gh-1048 ES6 classes](https://github.com/jshint/jshint/pull/1048) (13.05.19)
174+
- [gh-1608 Support ModuleImport
175+
expressions](https://github.com/jshint/jshint/pull/1608) (14.04.05)
176+
- [gh-1563 Add basic support for ES6
177+
TemplateLiterals](https://github.com/jshint/jshint/pull/1563) (14.03.21)
178+
179+
</span>
180+
181+
<span id="ref-3">
182+
[3] Issues involving changes to the spec:
183+
184+
- [gh-1123 A generator function shall contain a yield
185+
statement.](https://github.com/jshint/jshint/issues/1123)
186+
- [gh-1936 ES6 (`esnext`) error: `import * as foo from
187+
'bar'](https://github.com/jshint/jshint/issues/1936)
188+
- [gh-2019 ES6 classes with export default flagged as 'not
189+
defined'](https://github.com/jshint/jshint/issues/2019)
190+
- [gh-2144 Support more cases of ES6 module
191+
usage](https://github.com/jshint/jshint/pull/2144)
192+
- [gh-2197 ES6 (esnext:true), jshint says "Foo is not defined"... but it's
193+
defined!](https://github.com/jshint/jshint/issues/2197)
194+
- [gh-2395 jshint incorrectly supports the module x from 'y'
195+
format?](https://github.com/jshint/jshint/issues/2395)
196+
197+
</span>

0 commit comments

Comments
 (0)