
Is there any code in Firefox (as of 2020) that comes from Netscape Navigator? - aaronbrethorst
https://retrocomputing.stackexchange.com/questions/14229/is-there-any-code-in-firefox-as-of-2020-that-comes-from-netscape-navigator
======
hu3
> In fact, if my calculations are correct, out of 65,745 lines in the original
> nsprpub, 36,046 are present unchanged in the current version of nsprpub,
> i.e. 54.8%.

This supports the statement that code is read many times more than written. So
think about that when trying to be clever.

~~~
irrational
Clear is better than clever. Unfortunately there is no agreement on what is
clear and what is clever. I think arrow functions in JS are more clever than
clear, but I’ve had people tell me that my opinion is mistaken.

~~~
anonymoushn
is this because you think having one dynamically scoped variable is clearer
than having 0?

~~~
austincheney
I think arrow functions are less clear because they are always anonymous
functions. Anonymous functions complicate stack traces and performance
profiles.

~~~
minitech
They can’t be named in the same standalone way that non-arrow function
expressions can, but they do acquire names in some positions that get used in
stack traces and profiles.

    
    
      > ({ literalProperty: () => {} }).literalProperty.name
      'literalProperty'
    
      > ({ ['computedName']: () => {} }).computedName.name
      'computedName'
    
      > const variable = () => {};
      > variable.name
      'variable'
    

So if you want to name an arrow function, you can usually assign it to a
variable.

~~~
austincheney
That is three examples of assignments. The arrow functions remain anonymous.

* [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name)

* [https://developer.mozilla.org/id/docs/Web/JavaScript/Referen...](https://developer.mozilla.org/id/docs/Web/JavaScript/Reference/Functions/Arrow_functions)

~~~
roblabla
Your parent specifically talked about giving it a name in thte stack frame.
And assigning an anonymous function to a constant/object and using it through
that assignment will cause the stack trace to show a name.

~~~
austincheney
The only way to arbitrarily generate a JavaScript stack trace without an
error, in both modern browsers and Node, is the following code sample. In
order to prove the output of a stack trace you need logic that actually
produces a stack trace.

    
    
       new Error().stack
    

The following demonstrations take the prior examples and put the stack call
into the arrow function bodies and wrap that in an arbitrary function for an
additional line in the stack trace output.

The first example assigns the arrow function to an object property. And then
generates the name of the object's property name. This does nothing to
describe the function. Here is a better example:

    
    
        var stack,a=function(){({ myProperty: () => {stack = new Error().stack;} }).myProperty();};a();stack;
    

In the browser that outputs:

    
    
        "myProperty@debugger eval code:1:59
        a@debugger eval code:1:82
        @debugger eval code:1:102
    

Its a bit more clear in Node's REPL

    
    
        'Error\n' +
          '    at Object.myProperty (repl:1:59)\n' +
          '    at a (repl:1:82)\n' +
          '    at repl:1:102\n' +
          '    at Script.runInThisContext (vm.js:120:20)\n' +
          '    at REPLServer.defaultEval (repl.js:432:29)\n' +
          '    at bound (domain.js:429:14)\n' +
          '    at REPLServer.runBound [as eval] (domain.js:442:12)\n' +
          '    at REPLServer.onLine (repl.js:759:10)\n' +
          '    at REPLServer.emit (events.js:333:22)\n' +
          '    at REPLServer.EventEmitter.emit (domain.js:485:12)'
    

Essentially the stack traces represent a method call as designated by a
function whose identity is bound to an object property, but the function
itself remains unnamed. The second example is logically identical to the first
except for the minor syntax difference of array notation versus a word type
variable name.

The third example is logically different than the prior two examples:

    
    
        var stack,a=function(){var myVariable = () => {stack = new Error().stack;};myVariable();};a();stack;
    

Browser: "myVariable@debugger eval code:1:51 a@debugger eval code:1:71
@debugger eval code:1:81

Node: 'Error\n' \+ ' at myVariable (repl:1:51)\n' \+ ' at a (repl:1:71)\n' \+
' at repl:1:81\n' \+ ' at Script.runInThisContext (vm.js:120:20)\n' \+ ' at
REPLServer.defaultEval (repl.js:432:29)\n' \+ ' at bound (domain.js:429:14)\n'
\+ ' at REPLServer.runBound [as eval] (domain.js:442:12)\n' \+ ' at
REPLServer.onLine (repl.js:759:10)\n' \+ ' at REPLServer.emit
(events.js:333:22)\n' \+ ' at REPLServer.EventEmitter.emit (domain.js:485:12)'

The output of assigning an arrow function is identical, in both environments,
to assigning a regular anonymous function:

    
    
        var stack,a=function(){var myVariable = function () {stack = new Error().stack;};myVariable();};a();stack;
    

That is different than assigning to a named function:

    
    
        var stack,a=function(){var myVariable = function myFunctionName() {stack = new Error().stack;};myVariable();};a();stack;
    
        'Error\n' +
          '    at myFunctionName (repl:1:76)\n' +
          '    at a (repl:1:96)\n' +
          '    at repl:1:111\n' +
          '    at Script.runInThisContext (vm.js:120:20)\n' +
          '    at REPLServer.defaultEval (repl.js:432:29)\n' +
          '    at bound (domain.js:429:14)\n' +
          '    at REPLServer.runBound [as eval] (domain.js:442:12)\n' +
          '    at REPLServer.onLine (repl.js:759:10)\n' +
          '    at REPLServer.emit (events.js:333:22)\n' +
          '    at REPLServer.EventEmitter.emit (domain.js:485:12)'
    

And both of those are different to anonymous functions not assigned to a
variable. Both of the following examples produce the same output:

    
    
        var stack,a=function(){(function () {stack = new Error().stack;}());};a();stack;
    
        var stack,a=function(){() => {stack = new Error().stack;};};a();stack;
    
        'Error\n' +
          '    at repl:1:46\n' +
          '    at a (repl:1:65)\n' +
          '    at repl:1:71\n' +
          '    at Script.runInThisContext (vm.js:120:20)\n' +
          '    at REPLServer.defaultEval (repl.js:432:29)\n' +
          '    at bound (domain.js:429:14)\n' +
          '    at REPLServer.runBound [as eval] (domain.js:442:12)\n' +
          '    at REPLServer.onLine (repl.js:759:10)\n' +
          '    at REPLServer.emit (events.js:333:22)\n' +
          '    at REPLServer.EventEmitter.emit (domain.js:485:12)'
    

You can see in the first anonymous function example that an IIFE (immediately
invoked function expression) is used. Function's require identity, aside from
3 exceptions, otherwise they throw an error. The three exceptions are arrow
functions, IIFE, and function arguments.

So much of this discussion is nonsense though, because it doesn't make sense
to arbitrarily complicate your code with unnecessary objects merely to provide
your anonymous arrow functions with identity. The whole point of arrow
functions is to reduce syntax and thereby provide easier to read code, which
only the third of those three examples provide.

It is also helpful to understand that a function's name is an identity known
to the function, which means it is available to the internal logic of the
function as a local reference and not a scoped reference. The identity of a
variable name to which a function is assigned will always be a scoped
reference, and that distinction also results in different output in stack
traces.

Furthermore, none of those examples demonstrates the most important use case,
callbacks, or functions as arguments to event handlers. In Node the callbacks
become nested very quickly and often times many layers deep. Each use of an
arrow function is an anonymous line in the call stack and several layers of
anonymous calls is less helpful to read. It's not hopeless because the stack
trace provides the location of each call, but you have to dive into the code
on each line mentioned to see what is actually happening instead of just
reading the function names from a more helpful stack trace.

~~~
minitech
This seems like a very verbose retread.

What I was saying is if you are currently using a named function:

    
    
      function foo(bar) {
          // …
      }
    

you don’t lose the name by making it an arrow function:

    
    
      const foo = bar => {
          // …
      };
    

and yes, you can name your callbacks and event handlers like this before
passing them to functions. Introducing variables to name values (any values,
not just functions) doesn’t really complicate code. Many times, it can be a
readability improvement.

------
DonHopkins
I saved some choice examples of code from the awful X-Windows version of
Netscape Navigator, on my Motif Angst Page:

[http://art.net/~hopkins/Don/unix-
haters/x-windows/motif.html](http://art.net/~hopkins/Don/unix-
haters/x-windows/motif.html)

Including some classic comments like:

    
    
        /* sets the parent window to 0 to fool Motif into not generating a grab */
    

And:

    
    
        /*
         *    This is a horrible function which should not be needed.
         *    use it to put the resize method back the way the XlwMenu
         *    class initializer put it. Motif screws with this when
         *    the XlwMenu class gets instantiated.
         */

~~~
asveikau
As Motif expertise is now an obsolete skill, I don't think this ages well.
Short version: in some places, they don't like how the library works. In
others, they are working around library bugs. In all cases, they seem
_severely_ pissed off about it, which is probably a bigger issue than Motif.

~~~
not2b
Most of the anti-Motif comments are by jwz.

~~~
asveikau
I've generally liked his technical rants and writings. These don't really land
with me though. Maybe he was frustrated with some deadlines or something.

~~~
bsder
There is a reason that anybody who dealt with it called it Mogrief.

An entire GUI toolkit was written from scratch simply to replace Motif (Gtk).

This should tell you what you need to know.

~~~
vidarh
It was more to it than Motif being painful, though. Motif was not open, and
the open reimplementation (LessTif) was buggy.

~~~
DonHopkins
Another buggy painful non-open reimplementation of Motif, which arguably had
the silliest name of any user interface toolkit in the entire universe, was
Sun's and AT&T's (Unix System Laboratories) "MoOLIT", the Motif Open Look
Intrinsics Toolkit, that let you switch back and forth between those two
different competing looks and feels (both of which sucked in their own ways),
and which was based on "OLIT", then Open Look Intrinsics Toolkit, which itself
was based on the horrible X Toolkit Intrinsics (Xt), which was the root of all
evil.

>MoOLIT (Motif OPEN LOOK Intrinsics Toolkit) is a graphical user interface
library and application programming interface (API) created by Unix System
Laboratories in an attempt to create a bridge between the two competing look-
and-feels for Unix workstations at the time: OPEN LOOK and OSF Motif.

>The library provided common GUI features such as boxes, menus, lists, and
buttons, but allowed users to choose which look and feel they wanted at
runtime. It was a short-lived project, as the industry was moving towards
Motif as the de facto GUI standard, a trend culminating in the COSE initiative
in 1993.

Of course if you just wanted a laugh at the name, you could also use the X
Anathema Widgets (Xaw) toolkit, but I think MoOLIT was funnier. I cracked up
every time I saw some Sun marketing droid in a tie seriously talking about it.

[https://en.wikipedia.org/wiki/MoOLIT](https://en.wikipedia.org/wiki/MoOLIT)

[https://en.wikipedia.org/wiki/OLIT](https://en.wikipedia.org/wiki/OLIT)

[https://en.wikipedia.org/wiki/OPEN_LOOK](https://en.wikipedia.org/wiki/OPEN_LOOK)

[https://en.wikipedia.org/wiki/Motif_(software)](https://en.wikipedia.org/wiki/Motif_\(software\))

[https://en.wikipedia.org/wiki/X_Toolkit_Intrinsics](https://en.wikipedia.org/wiki/X_Toolkit_Intrinsics)

[https://en.wikipedia.org/wiki/X_Athena_Widgets](https://en.wikipedia.org/wiki/X_Athena_Widgets)

>In a talk for USENIX, X pioneer Jim Gettys remarked that although Athena
widgets were "ugly", they were often used in the period of X history that he
describes as the "GUI wars", as a safe alternative to the competing Motif and
Open Look toolkits.

------
tyingq
Server side, so not in Firefox, but I personally got a lot of mileage out of
NSAPI. For the company I worked at, at the time, it was the only way to do
something better than old-school, fork a process per request, CGI. We had
persistent socket processes handling web requests, in parallel, WAY before
things like mod_perl or FastCGI. As I remember, it was there around 1995 or
so. Many thanks to any former Netscapers. For comparison mod_perl was 1999 or
so. FastCGI was really beta and unknown (as I remember) in late 96.

~~~
balnaphone
> For comparison mod_perl was 1999 or so

I used mod_perl extensively in the summer (May-Aug) of 1996; it was the only
way I found to embed perl directly into the server process, at the time.

See also
[http://apache.perl.org/about/history.html](http://apache.perl.org/about/history.html)

~~~
tyingq
Ahh. Okay. My memory was off then. Sounds like mod_perl co-existed with NSAPI.

------
jasonkester
It's worth noting that it was Netscape Navigator 6 that this was all based on.
As in, the ground-up rewrite of the entire product that ultimately killed the
company. You know, the one that was so different to its predecessor that it
couldn't render Netscape.com.

So yes, maybe some "Netscape" is in there still. Just not Netscape 4, the good
one we think about when remembering Navigator.

~~~
toyg
Netscape 4 was utter rubbish. There is a reason it was rewritten: it had lost
the browser war, because it couldn’t be updated quickly enough to keep up with
IE’s rate of adoption of new standard features.

------
rvp-x
That "stack grows upwards" conditional is a giveaway of ancient code. The only
architecture I know still using that regularly is PA-RISC, and it's very rare
for people to care about it today.

------
mintplant
Searchfox is super handy for spelunking through the Mozilla codebase. For
example: [https://searchfox.org/mozilla-
central/search?q=Netscape+Comm...](https://searchfox.org/mozilla-
central/search?q=Netscape+Communications&path=)

------
kbumsik
Contributed Firefox a little bit two years ago. Here is the file I
contributed: [1]

You will immediately see a lot of NS_ (or ns) prefixed names in the source
code. Without knowing about Firefox's history I thought like that Firefox has
history with Apple (NeXTSTEP). But no, NS_ are the legacy from Netscape.

It was fun to get to know its history from the source code when I was
contributing it :)

[1]: [https://dxr.mozilla.org/mozilla-
central/source/dom/media/Med...](https://dxr.mozilla.org/mozilla-
central/source/dom/media/MediaRecorder.cpp)

~~~
DonHopkins
Apple uses a lot of historical legacy NS prefixes too, but in their case it
stands for NeXT Step! ;)

I used to call the browser Netscapé, which rhymes with Nescafé, back in the
90's when it was the world's leading distributer of Java.

[https://en.wikipedia.org/wiki/Nescaf%C3%A9](https://en.wikipedia.org/wiki/Nescaf%C3%A9)

>Nescafé is a brand of coffee made by Nestlé. It comes in many different
forms. The name is a portmanteau of the words "Nestlé" and "café". Nestlé
first introduced their flagship coffee brand in Switzerland on 1 April 1938.

------
bits_of_bytes
Lots of Microsoft Edge (pre chromium) code that stretched back to at least IE4
(along with comments with TODOs for long departed employees)

The style around naming, spacing, etc was very different, and not always
cleaned up, so it was easy to tell what was old.

------
tpmx
Is Firefox still using using that horrible COM-workalike from Netscape/Mozilla
(XPCOM)? This was the thing that immediately turned me off from this codebase
back in the late 90s.

To this day, I remember the excitement from the buildup to the first open
source release of "Mozilla (Netscape 4.something)"... and then downloading the
code and seeing this horrible complexity. And suddenly understanding why
Netscape was so dysfunctional.

~~~
DonHopkins
There is actually a technical term of art (two actually) for the process of
removing XP/COM interfaces from Mozilla: "decomification" and
"decomtamination", and another related term "outparamdelling".

[https://news.ycombinator.com/item?id=20266627](https://news.ycombinator.com/item?id=20266627)

>It certainly had a lot of problems and limitations, and
OLE/ActiveX/DCOM/DirectX/etc took it way too far, then Mozilla XP/COM cloned
it and also took it way too far (and then back again: see "decomification" and
"decomtamination"), but it really was a pretty elegant and successful solution
to the problems it was designed to address at the time.

[https://wiki.mozilla.org/Gecko:DeCOMtamination](https://wiki.mozilla.org/Gecko:DeCOMtamination)

[http://taras.glek.net/blog/categories/decomtamination/](http://taras.glek.net/blog/categories/decomtamination/)

[https://blog.mozilla.org/tglek/category/decomtamination/](https://blog.mozilla.org/tglek/category/decomtamination/)

[https://news.ycombinator.com/item?id=12968830](https://news.ycombinator.com/item?id=12968830)

>Mozilla underwent a process of "DeCOMification", because they went too far
with XP/COM, and wanted to dial it way back.

[https://bugzilla.mozilla.org/buglist.cgi?query_format=specif...](https://bugzilla.mozilla.org/buglist.cgi?query_format=specific&order=relevance+desc&bug_status=__all__&product=&content=decomify&comments=0&comments=1)

>Can someone link to a synopsis describing what "COM" is? It's hard to search
for. (e.g. microsoft com visual studio)

[https://news.ycombinator.com/item?id=12975257](https://news.ycombinator.com/item?id=12975257)

>Glad you asked! One of my favorite topics. ;)

[...]

>And Mozilla came up with XP/COM [14], for implementing components in
Mozilla/Firefox/XULRunner/etc, enabling programmers to implement and consume
XP/COM components in C++ or JavaScript. Of course it has its own IDL and
tooling, and suffers from many of the same problems that COM did.

>Mozilla didn't go nearly as far down the rabbit hole as Microsoft did, and
later backtracked in their valiant "deCOMification" aka "deCOMtamination" and
"outparamdelling" efforts [15].

An example of outparamdelling:

[https://bugzilla.mozilla.org/show_bug.cgi?id=455943](https://bugzilla.mozilla.org/show_bug.cgi?id=455943)

~~~
tpmx
It took them so much time. I can't even begin to imagine how money it cost
them to fix this. 10 years * 500 full times at SV salaries, or something like
that? That is one expensive bad architectural decision. Maybe $0.5-1 billion,
in the end? Not counting missed opportunities during that whole decade.

Is the shame of this the reason Marc A doesn't want to talk about Netscape?

~~~
DonHopkins
With 2020 hindsight (literally: it's now the year 2020! ;), I think Netscape
should have just gone all-in on JavaScript, forgotten about XP/COM and its
ilk, and made JavaScript itself the hub for extension and component
integration, by giving it an excellent robust native code integration and
extension API like Python has, and plugging things into JavaScript directly,
instead of plugging things directly into the web browser itself with XPCOM or
NPAPI or ActiveX, and thumb-tacking JavaScript onto the side as an
afterthought, like a second-class red-headed bastard stepchild.

It wouldn't have been "rocket science": Python already existed at the time,
with an excellent extension and embedding API, and was well known and widely
used that way. TCL was another contender that also had an excellent native
code integration API, although it was a much worse language than Python.

But there were politics around TCL, because Sun had hired John Oosterhout, its
author, and arrogantly unilaterally announced that they were making TCL the
web's official scripting language by administrative fiat, leading to the great
"TCL War" kicked off by RMS's infamous but insightful "Why you should not use
TCL" posting. Then Sun dropped TCL like a hot potato, and started pushing Java
obsessively instead.

[https://vanderburg.org/old_pages/Tcl/war/0000.html](https://vanderburg.org/old_pages/Tcl/war/0000.html)

[https://news.ycombinator.com/item?id=17059077](https://news.ycombinator.com/item?id=17059077)

And of course NetScape also went a long way down the misguided road of Java
applets, and worse yet "100% Pure Java TM", by announcing they were going to
rewrite the entire browser in Java. In which case, instead of cloning
Microsoft COM and using XP/COM as a component extension hub, they would have
ended up being stuck with Java's awful "JRI" native code integration API,
which was eventually superseded by the also-awful "JNI".

The problem with using Java as an integration hub was that Sun was
ideologically opposed to integrating Java with any other languages, because
they thought everyone should throw away all their own code and rewrite
everything in "100% Pure Java TM" (linguistic supremacy instead of linguistic
inclusivity).

To encourage or even allow developers to use some other language than Java
would be to admit that Java wasn't perfect for everything and superior to
every other language, which Sun couldn't bring themselves to do after
launching their "100% Java TM" campaign. So they tried to shame and refused to
support anyone who wanted to integrate Java with native code, instead of
rewriting everything in Java from scratch, like Netscape tried to do but
eventually gave up on.

So Sun downplayed and strangled JRI in the crib, and they also didn't give a
shit about its successor JNI either, and let it wither on the vine, because
they refused to recognize the importance of using any other language than
Java, once they got obsessed with their "100% Pure Java TM" craze.

NetScape suffered from the Java/JRI albatross around their neck for a long
time:

[https://en.wikipedia.org/wiki/NPAPI#LiveConnect](https://en.wikipedia.org/wiki/NPAPI#LiveConnect)

>The disadvantage of LiveConnect is that it is heavily tied to the version of
Java embedded within the Netscape browser. This prevented the browser from
using other Java runtimes, and added bloat to the browser download size since
it required Java to script plugins. Additionally, LiveConnect is tricky to
program: The developer has to define a Java class for the plugin, run it
through a specialized Java header compiler and implement the native methods.
Handling strings, exceptions and other Java objects from C++ is non-obvious.
In addition, LiveConnect uses an earlier and now obsolete application
programming interface (API) for invoking native C++ calls from Java, called
JRI. The JRI technology has long since been supplanted by JNI.

I wonder why NetScape didn't choose Python in the first place, instead of
inventing their own language or using TCL or Java. Lua would have also been a
great choice, but it wasn't nearly as far along, mature, widely supported, and
popular as Python was at the time. It was probably because they just wanted to
invent their own language, and not use something off-the-shelf that was
already widely supported and just worked: NIH.

Here's some other stuff I wrote about the development of component
technologies and Java during that time:

[https://news.ycombinator.com/item?id=19837817](https://news.ycombinator.com/item?id=19837817)

>Wow, a blast from the past! 1996, what a year that was.

>Sun was freaking out about Microsoft, and announced Java Beans as their
vaporware "alternative" to ActiveX. JavaScript had just come onto the scene,
then Netscape announced they were going to reimplement Navigator in Java, so
they dove into the deep end and came up with IFC, which designed by NeXTStep
programmers. A bunch of the original Java team left Sun and formed Marima, and
developed the Castanet network push distribution system, and the Bongo user
interface editor (like HyperCard for Java, calling the Java compiler
incrementally to support dynamic script editing).

[https://donhopkins.com/home/interval/pluggers/](https://donhopkins.com/home/interval/pluggers/)

[https://donhopkins.com/home/interval/pluggers/requirements.h...](https://donhopkins.com/home/interval/pluggers/requirements.html)

[https://donhopkins.com/home/interval/pluggers/navigator.html](https://donhopkins.com/home/interval/pluggers/navigator.html)

[https://donhopkins.com/home/interval/pluggers/java.html](https://donhopkins.com/home/interval/pluggers/java.html)

I'd love to hear from somebody who was at Netscape at the time, about what
they thought of Python, whether or not they fairly considered it, and why they
didn't end up using it instead of rolling their own language from scratch. And
also what Netscape's view of the great "TCL War" was from their perspective,
and why they chose to collude with Sun's Java Manifest Destiny for so long,
but earlier they didn't play along with Sun's announcement that TCL would be
the world's official web scripting language. Besides the obvious fact that
Java was much better than TCL, yet TCL for all its flaws and limitations at
the time was certainly better than initial version of JavaScript (LiveScript),
which was awful.

~~~
kalleboo
Brendan Eich wanted to do Scheme, but then edict came from above that "it has
to look like Java" [https://thenewstack.io/brendan-eich-on-creating-
javascript-i...](https://thenewstack.io/brendan-eich-on-creating-javascript-
in-10-days-and-what-hed-do-differently-today/)

------
canada_dry
Makes me wonder, is there a tool like grammarly [1] for source code? One that
checks for large chunks of copied code from other open source projects?

[1] [https://www.grammarly.com/plagiarism-
checker](https://www.grammarly.com/plagiarism-checker)

~~~
bjterry
I interned at a company called Palamida that did this around 2006. They were
eventually acquired by Flexera. One of their competitors was Black Duck
Software which was acquired by Synopsys.

------
jsjddbbwj
Is there any code in WebKit that comes from khtml?

Is there any code in Source that comes from idtech 2?

~~~
qznc
For a small personal project [0], it was 14 lines after three years continued
in a company.

[0]
[http://beza1e1.tuxen.de/tipiwiki.html](http://beza1e1.tuxen.de/tipiwiki.html)

~~~
rozab
This was a good read. Question from a naive programmer: the writer mentions
'cute comments' in the codebase, like

    
    
        // Assertion: Now we know the name of the current page
    

Is this style frowned upon? I've always thought it's a very clear way of
communicating. There's a reason many maths papers are written like this. Do my
co-workers think my comments are silly? :(

~~~
qznc
Comments is a mostly subjective topic. In this case, I have two arguments
against the comment.

First, it just says what the three simple lines of code above did. Comments
should rather focus on the "why" to provide information which the code cannot
give.

Second, assertions should be code (or somehow machine readable).

------
jmspring
A lot of the code in libnss (security code) looks quite similar to code that
was written in the mid 90s. I don't have archives, but browsing multiple files
there is a lot of familiarity there.

------
ape4
Of course, lots of Firefox is Rust now. (edit: I'm saying "lots", not "most")

~~~
MBlume
I don't think this is true? I think Mozilla is interested in using Rust for
new code where that makes sense, but the vast majority of Firefox as shipped
today is still C++

~~~
stonewareslord
They're working on porting it. See Oxidation Project:
[https://wiki.mozilla.org/Oxidation#Rust_Components](https://wiki.mozilla.org/Oxidation#Rust_Components)

e: Edit url to point to rust status in Firefox

~~~
dblohm7
Only in specific cases. See the “Recommendations” section in that document.

