JSHint: Wrestling it Free
This is the final essay in a four-part series about relicensing the JSHint software project.
The struggle to relicense JSHint was about to get ugly. We’d decided to forcibly take control by rewriting targeted sections of the source code. To be fair, we weren’t looking for trouble. We tried to get permission from every contributor, but that turned out to be impossible. We turned to rewriting only reluctantly because of the danger in swapping out pieces of such a complex and widely-distributed program. Just the thought gave us chills.
The good news was that the signature effort, though incomplete, reduced the
risk. Instead of rewriting the
jshint.js file in its entirety, we’d only have
to rewrite the bits which were contributed by folks who hadn’t permitted the
license change (there were five in total). Less changed code meant less chance
of regression. On the other hand, it also meant the general public might have
less confidence in the legitimacy of our approach.
See, the JSON license applies to “all copies or substantial portions of the Software.” Source code that is re-written from scratch will naturally bear little resemblance to its predecessor. For all the challenge posed by a “clean slate” rewrite, we could at least take it for granted that the result would be vastly different from the original and that the old license wouldn’t apply.
Contrast that with the partial rewrite we were now considering. Source code that’s patched with incremental changes will tend to look pretty similar. It’s not that you can’t relicense through partial rewrite; you just have to be really careful.
In this essay, I’ll talk about how we were really careful.
Fresh faces, clean rooms
It’s sometimes said that if you want something done right, you have to do it yourself. I certainly could have made short work of this. Thanks to years of maintaining JSHint, I was full of ideas about how this loop or that method could be refactored. Trouble was, my familiarity with the codebase was a double-edged sword. There could be no denying that I was influenced by the original code, undermining the premise that the new version was not a “copy or substantial portion of the Software.” That’s why I wanted brand new contributors to do the rewriting.
I began searching for help, very quietly at first. Relicensing is a defiant act, and you never look sillier than when you fail to do something defiant. Call me egotistical, but I didn’t want to wind up with the proverbial egg on my face. That timidness didn’t last long.
Meanwhile, I prepared working environments for the yet-to-materialize volunteers. For each patch that needed to be rewritten, I created a copy of the project with that code (and the change history) removed. This way, the new contributor’s fresh perspective wouldn’t be tainted by the code they were replacing. Critically, JSHint’s creator had been careful to license all the project’s automated tests with the MIT Expat license, so I could also share the tests with the volunteers. The tests would fail with the code removed, but for software developers, there’s no clearer acceptance criteria than a set of failing tests. I could simply tell each volunteer, “please get the tests to pass,” and we could both be confident about when their work was done. Since each task was cordoned off to a distinct and inert environment, I began thinking of these repositories (five in total) as “clean rooms.”
Except that despite my best efforts, participants were not exactly lining out the door. For over a year following Ethan’s contribution, we made no progress. I onboarded a few candidates, but none made meaningful advances. As you might imagine, this was a pretty discouraging year.
Until one day, Alex Kritchevsky stumbled across the issue and contacted the JSHint maintainers:
I came across https://github.com/jshint/jshint/issues/1234, and heard you were looking for someone who knows JS and would like to help with free software.
Alex completed Ethan’s work over the next few weeks. Amazingly, their work surfaced latent bugs in the original implementation. The final rewrite was in some ways more correct than the original! The new version also introduced a few new bugs, but that was expected. We stamped out the regressions in no time. Really, it’s incredible that this code was re-architected at all, let alone by unpaid strangers and with such high fidelity. Looking back, I’m still impressed by Ethan and Alex’s commitment and technical abilities.
As impressive as that work was, the project would continue to be stuck with a non-free license until we finished the job. After years of outreach, mentorship, and painfully rare developments, continuing along this path seemed unwise. I started to reconsider my decision to abstain from the rewrite.
Getting my hands dirty
For all my reluctance to participate directly, a famous event in the free software movement offered some inspiration.
[Richard Stallman] read Symbolics’ source code changes to find minor bugs they had fixed, and fixed each of them differently. […] When Symbolics excluded its source changes from redistribution, as a means to defeat its rival [LMI], Stallman determined to thwart Symbolics’ goal. By holing up in his MIT offices and writing equivalents for each new software feature and fix, he gave users of the MIT system, including LMI customers, access to the same features as Symbolics users.
Stallman’s situation seemed roughly analogous. Actually, the risk he faced seemed even greater. He wasn’t defying some ludicrous contract term; he was up against a private enterprise with a vested interest in maintaining authority. If Stallman could rewrite and redistribute Symbolic’s source code, then why couldn’t I do the same with JSHint’s?
This line of reasoning was only so convincing, though. The term “minor bug” is pretty vague, though it wasn’t clear if the distinction even mattered. More importantly, the Symbolics showdown took place over 30 years ago. Legal frameworks surrounding source code have matured quite a bit since then.
Rather than risking the legitimacy of the effort on a scrap of technological folklore, I decided to get advice from an authority. I reached out to the Harvard Law School Cyberlaw Clinic in the hopes that they could provide some pro-bono education. And guess what? They could!
Russell Hoover, a student working under Kendra Albert, studied the particulars of this situation and relevant case law. They explained the alternatives available and offered some thoughts on the risks of each. After weighing the options in this careful research, I decided to do some of the rewriting myself.
The challenge was deeply satisfying and prompted a lot of feelings. There was the feeling of solidarity with respected contributors. The feeling of agency over a problem that you’d long considered out of your control. The feeling of relief from improving a system you’ve been involved with for years. Even the feeling of defiance from working with the cards stacked against you.
Fellow maintainers Rick Waldron and Caitlin Potter provided characteristically thorough peer review. This time, in addition to verifying correctness, they also made sure that my work was substantially different than the code it replaced.
I rewrote two patches in total. This left just two more–patches so tiny that I couldn’t find a way to rewrite them in a substantially different way. For these, I reused the “clean room” approach, asking former coworkers Matt Surabian and Tyler Kellen for the quick favor of a rewrite. They each completed their task in a matter of days.
And then, the rewrite was done.
I documented the technical details of the relicensing effort in the project
repository, merged the license change to the
master branch, and released the
result as 2.12.0, the first free software version of
Hundreds of people collaborated to make this change. For each one, there are a thousand more like-minded individuals, working in recognition of your dignity and eager defend it.
So whether you’re writing code or installing an app, the next time you reach for a new piece of software, remember this story. Stop and consider whether you agree to the terms under which the software is provided. If you don’t understand them (whether due to JSON-like vagueness or Apple-like specificity), take that personally. Find an alternative that respects your freedom.