ES5 to ES3 Syntax Converter
Convert ES5 JavaScript to ES3-compatible syntax. Quotes reserved word properties, converts dot notation, removes trailing commas for IE8 support.
About
Legacy JavaScript engines conforming to ECMA-262 3rd Edition (ES3) - notably Internet Explorer 8 and below - treat reserved words as syntax errors when used as bare property identifiers. Code like obj.class or {return: 1} will throw a parse error in these engines, silently breaking entire application bundles. This tool performs the three critical transformations required for ES3 compliance: quoting reserved-word property keys in object literals, converting reserved-word dot-access to bracket notation, and stripping trailing commas from arrays and objects. It processes against the full set of 38 reserved words defined in ECMA-262 ยง7.5.1 through ยง7.5.3.
The converter operates as a context-aware parser, not a naive regex replacement. It tracks string literals, comments, and regular expression contexts to avoid corrupting quoted content. This matters in production: a blind find-and-replace on the word class would destroy CSS class strings and comment documentation. Note: this tool handles syntactic downgrading only. It does not polyfill ES5 runtime methods such as Array.prototype.forEach or Object.keys. For full ES3 deployment you still need runtime shims like es5-shim.
Formulas
The converter applies three transformation rules in sequence. Each rule operates only on tokens outside of string literals, comments, and regular expression literals.
Rule 1 - Quote Reserved Property Keys:
input: { reservedWord : value } โ output: { "reservedWord" : value }
For each unquoted identifier k in an object literal key position, if k โ ReservedWords, replace k with "k".
Rule 2 - Convert Dot Access to Bracket Notation:
expr.reservedWord โ expr["reservedWord"]
For each member expression obj.prop, if prop โ ReservedWords, rewrite as obj["prop"].
Rule 3 - Remove Trailing Commas:
[ a, b, ] โ [ a, b ]
{ k: v, } โ { k: v }
Match any comma followed by optional whitespace and a closing ] or }. Remove the comma while preserving whitespace structure.
Where ReservedWords = the union of all ES3 Keywords (ECMA-262 ยง7.5.2) and FutureReservedWords (ยง7.5.3), totalling 53 identifiers. The context tracker uses a finite state machine with states: NORMAL, STRING_SINGLE, STRING_DOUBLE, COMMENT_LINE, COMMENT_BLOCK, REGEX. Transitions are triggered by character sequences like //, /*, */, and quote characters, with escape sequence awareness via backslash tracking.
Reference Data
| Reserved Word | Category | Object Key Fix | Dot Access Fix |
|---|---|---|---|
| break | Keyword | {"break": v} | o["break"] |
| case | Keyword | {"case": v} | o["case"] |
| catch | Keyword | {"catch": v} | o["catch"] |
| class | Future Reserved | {"class": v} | o["class"] |
| const | Future Reserved | {"const": v} | o["const"] |
| continue | Keyword | {"continue": v} | o["continue"] |
| default | Keyword | {"default": v} | o["default"] |
| delete | Keyword | {"delete": v} | o["delete"] |
| do | Keyword | {"do": v} | o["do"] |
| else | Keyword | {"else": v} | o["else"] |
| enum | Future Reserved | {"enum": v} | o["enum"] |
| export | Future Reserved | {"export": v} | o["export"] |
| extends | Future Reserved | {"extends": v} | o["extends"] |
| finally | Keyword | {"finally": v} | o["finally"] |
| for | Keyword | {"for": v} | o["for"] |
| function | Keyword | {"function": v} | o["function"] |
| if | Keyword | {"if": v} | o["if"] |
| import | Future Reserved | {"import": v} | o["import"] |
| in | Keyword | {"in": v} | o["in"] |
| instanceof | Keyword | {"instanceof": v} | o["instanceof"] |
| new | Keyword | {"new": v} | o["new"] |
| return | Keyword | {"return": v} | o["return"] |
| super | Future Reserved | {"super": v} | o["super"] |
| switch | Keyword | {"switch": v} | o["switch"] |
| this | Keyword | {"this": v} | o["this"] |
| throw | Keyword | {"throw": v} | o["throw"] |
| try | Keyword | {"try": v} | o["try"] |
| typeof | Keyword | {"typeof": v} | o["typeof"] |
| var | Keyword | {"var": v} | o["var"] |
| void | Keyword | {"void": v} | o["void"] |
| while | Keyword | {"while": v} | o["while"] |
| with | Keyword | {"with": v} | o["with"] |
| abstract | Future Reserved | {"abstract": v} | o["abstract"] |
| boolean | Future Reserved | {"boolean": v} | o["boolean"] |
| byte | Future Reserved | {"byte": v} | o["byte"] |
| char | Future Reserved | {"char": v} | o["char"] |
| double | Future Reserved | {"double": v} | o["double"] |
| final | Future Reserved | {"final": v} | o["final"] |
| float | Future Reserved | {"float": v} | o["float"] |
| goto | Future Reserved | {"goto": v} | o["goto"] |
| implements | Future Reserved | {"implements": v} | o["implements"] |
| int | Future Reserved | {"int": v} | o["int"] |
| interface | Future Reserved | {"interface": v} | o["interface"] |
| long | Future Reserved | {"long": v} | o["long"] |
| native | Future Reserved | {"native": v} | o["native"] |
| package | Future Reserved | {"package": v} | o["package"] |
| private | Future Reserved | {"private": v} | o["private"] |
| protected | Future Reserved | {"protected": v} | o["protected"] |
| public | Future Reserved | {"public": v} | o["public"] |
| short | Future Reserved | {"short": v} | o["short"] |
| static | Future Reserved | {"static": v} | o["static"] |
| synchronized | Future Reserved | {"synchronized": v} | o["synchronized"] |
| throws | Future Reserved | {"throws": v} | o["throws"] |
| transient | Future Reserved | {"transient": v} | o["transient"] |
| volatile | Future Reserved | {"volatile": v} | o["volatile"] |