in ,

JavaScript Errors: An Exceptional History, Hacker News

JavaScript Errors: An Exceptional History, Hacker News


Hello again! It’s a historic week here at AppSignal! ********

This week we released the first version of our new and improvedJavaScript error monitoring. Now you can have your front end code, Ruby or Elixir back end code, your hosts, performance, everything monitored in one interface.

To celebrate the launch, in a two-part series of posts, we’ll be taking a look at the history of Errors in JavaScript, including how to handle them in your code today. In this part, join us as we go through the origins and turbulent years of growth of JavaScript and see it grow into the language it is today.

A Comedy of Errors

In accordance withMurphy’s Law, arguably ticket # 1 on the backlog of the great Jira board of the universe, runtime errors have existed as a concept since the very first version of JavaScript, shipped as part of Netscape Navigator 2.0 in 1995, and later as part of the second iteration of Internet Explorer.

Here in 2019, it’s difficult to conceive of a primordial version of JavaScript. Famously prototyped in 10 days, and publicly released mere months later, the early history of JavaScript exists as a flawed, but nonetheless impressive, monument to compromise and short- term corporate thinking; plans to implementSchemeas the embedded scripting language in Netscape Navigator gave way to desires to include a “glue language” to compliment Java, producing a hybrid of syntax vaguely resembling Java but with ideas cribbed from dynamically typed languages ​​likeScheme,HyperTalkandSelfin order to differentiate itself from the more “serious ”And statically typed Java.

One Point Uh-Oh

JavaScript 1.0 shipped without some common language features. For instance, support for a list-like data structure (theArrayobject was added in version 1.1). Object and array literals () []and{}) would not arrive until JavaScript 1.2. Some features changed rapidly – JavaScript 1.2 changed the==and!=operators to make them no longer coerce types if the compared values ​​were not of the same type. This would later be reversed with version 1.3 with the advent of the ECMA standardization, and the===and!==operators would fill the gap.

Perhaps most pertinent to the theme of this post, however, JavaScript shipped without the ability to handle runtime errors. If your script produced a runtime error, at the time, there was no mechanism to recover from this. A runtime error would “crash” the page, and present the user with an ugly, cryptic error message and no other option than to reload and hope that, fingers crossed, the script would evaluate correctly this time. Those of us using the web in those days don’t get the warm-and-fuzzies when we remember the dreaded un-closable “Script error” dialog, but luckily those days are far behind us.

The wake of these, and many other, decisions of those ten days in May 1995 has stretched unusually far into the future. It can be argued that the perception of JavaScript as a folly, a mere toy language for those not competent enough to embrace “real” languages, is birthed from these early design flaws and Netscape’s own marketing attempts to position JavaScript as a sidecar to Java, a reputation that has been hard for JavaScript to shake as its adoption and ubiquity grows.

Ultimately, however, extensions were made to the JavaScript language to address many of these initial hurdles, leading to the eventual standardization of JavaScript as ECMAScript in 1997, the formation of TC 39, and the beginning of the tumultuous journey to the JavaScript of today.

An Exceptional History

The first version of the ECMA – 262 standardization of JavaScriptincluded a section on errors short enough to be almost memorizable. It talks very little about runtime errors, only hinting at “catchable [errors] in future versions”. It would take until the 3rd Edition of ECMA – 262 (colloquially known as ES3) for proper exception handling semantics to be ratified as part of the ECMAScript specification.

In the meantime, it would be Netscape who would take the initial steps and add two of the core pillars of JavaScript error handling.

window.onerror

Version 1.1 of JavaScript (shipped with Netscape Navigator 3.0), would be the first to have a mechanism for error handling of any kind, in the form of thewindow.onerrorevent. JavaScript was designed as an event-driven language from the very beginning.

Inthe Netscape Navigator 3.0 documentation, thewindow.onerrorevent is originally defined as firing when “the loading of a document or image causes an error”.

In Navigator 3.0, handling an error would look like this:

1 2 3 4 5
functiononError() ************************** (msg),(url),(Lineno)){  // error handling code here!}window.onerror=onError

This enabled JavaScript developers of the time to create something resembling a trace from the arguments provided to the event handler but did not offer any solutions with regards from recovering from an error.

try/catch

Basic exception handling constructs liketry/catchandthrowwere not a part of language until JavaScript 1.4, a version of JavaScript that was only used for Netscape LiveWire, a server-side JavaScript implementation released in 1999, predating Node.js by a decade. They do not appear in the ECMAScript specification until version 3. This can be considered the second “true” version of the ECMAScript standard (ECMAScript 2 contained only editorial changes).

Although exception handling as a concept predates it by many years in both software and hardware,try/catchexception handling was a concept first introduced in software in C and later extended with thefinallyblock in Java. A program can “try” executing a block of code that may throw an exception, and interrupt the normal flow of execution of our program and execute code defined in thecatchblock if it does.

Athrowstatement will pass the value to its right- hand side to the first argument of thecatchblock. This could be any value; a common pattern in JavaScript was to throw a string and handle the error conditionally. Over time, conventions and best practices evolved, and it would become more common to throw anErrorobject instead. No further statements beyond thethrowstatement will execute. Instead, the code inside thecatchblock will execute. This allows a developer to write logic to recover from runtime errors or log them somewhere for debugging at a later stage.

Thefinallyblock always executes, regardless of whether an exception was thrown or caught. If no catch block exists in the call stack when an exception is thrown, the script will simply terminate.

1 2 3 4 5 6 7 8 9
try{  Throw"I'm broken"// generates an exception}catch(e){  // statements to handle any exceptions}finally{  // clean up}

This change to JavaScript syntax would modify the semantics of thewindow.onerrorhandler somewhat. As many errors could now be handled at runtime, thewindow.onerrorwould begin to evolve into a funnel for unhandled exceptions.

TheErrorobject

Another crucial ingredient of the JavaScript error handling picture is theError (object.)

The Error page on MDN is a fascinating read in itself. TheErrorobject is a compendium of inconsistency - a child of the badlands of the late 90 's and oughts, an era in web development where new JavaScript features, rather than introduced and standardized on a yearly basis in a co-operative effort between vendors and developers like they are today, were created in a standoff of sorts between two major browser vendors vying for dominance of an industry in its infancy.

The roots of theErrorobject can betraced back to JScript 5, Microsoft's own reverse-engineered implementation of the ECMAScript standard and included in Internet Explorer. This marked the first time that instances of anErrorobject could be thrown when runtime errors occurred, and could also be inherited from to create custom exceptions.

1 2 3 4 5 6 7 8 9 10 11 12
functionbroken(){  if(true){    ThrownewError()  "I am an error")  }}try{  broken()}catch((e)){  // e.name="Error"  // e.message="I am an error"}

Early documentation from Netscape Navigator exists that implies the creation of your own custom exception object was expected, however Microsoft was somewhat ahead of the curve here with a more detailed exception object that could be thrown in place of a primitive value like a string.

A quirk of the early MicrosoftErrorobject compared to the ECMA-standardized version is that the alternative arguments you could provide:

(1)
new Error (num: number, description ?: string)

The first argument was intended to be a value which, when combined with the&(bitwise And) operator to combine the number property with the hexadecimal number0xFFFF, would return the actual error code.

The existence of theErrorobject was later given legitimacy as part of the ECMAScript 3 specification, however, it's implementations remain inconstant across browsers to this day. TheErrorobject as specified in ECMA - 262 has two intrinsic properties: the description of the error (message,descriptionin earlier Microsoft implementations) and the name of the error (name).

However, browser vendors have since added their own extensions to theErrorobject, the most notable of which being thestackproperty, returning a string representation of which functions were called leading up to the exception, in what order, from which line and file, and with what arguments. Although not part of the ECMAScript standard, almost all modern browsers include anErrorobject with astackproperty. Older browsers, such as IE9, do not include this functionality.

Backtracing to today

This brings us back to today. TheAppSignal JavaScript librarydepends heavily on thestackproperty's presence to provide a backtrace in the UI - if it's not present, then there's no backtrace that we can display.

In some cases (namely inside theplugin for window events), we attempt to construct a partial stack trace if none is present from the best information available at the time, but in some situations, no stack trace will be available at all . Luckily for all of us, the percentage of browsers in use today that do not support theErrorobject'sstackproperty is relatively marginal.

That’s it for now!

Next time, we'll look at how errors are handled in JavaScripttoday, including methods to handle asynchronous code and how to best use the AppSignal JavaScript library to track them.

We're super excited to have our JavaScript error tracking out in the wild, so pleasegive it a tryand tell us what you think.

If you liked this post,subscribe to our new JavaScript Sorcery listfor a monthly deep dive into more magical JavaScript tips and tricks.

Brave Browser
Read More
Payeer

What do you think?

Leave a Reply

Your email address will not be published. Required fields are marked *

GIPHY App Key not set. Please check settings

Gold Price Rips Lower After Massive Selloff as Dollar Spikes, Dow Hovers Near All-Time High, Crypto Coins News

Gold Price Rips Lower After Massive Selloff as Dollar Spikes, Dow Hovers Near All-Time High, Crypto Coins News

RIP OG Pixel: Google ends support after just three years, Ars Technica

RIP OG Pixel: Google ends support after just three years, Ars Technica