JavaScript Syntax Checker

Paste a snippet. The tab compiles it as a function body and stops. Missing braces surface with a line number. The paste never runs. Modules and TypeScript fail here on purpose.

JavaScript compile bench

Compile only Function constructor ยท paste never runs

Known traps

Waiting for a paste
Lines
0
Bytes
0
Engine
Function

The receipt fills after compile. Click a finding to jump to the line.

This page used to run your paste. That was a mistake.

An earlier build wrapped the snippet in new Function and then called the result. A syntax pass became a live interpreter sitting on a public page. fetch ran. Cookies were readable. A tight loop froze the tab. People pasted production helpers, forgot a debug call was still in the body, and watched the helper fire against whichever host still held a session.

The invoke is gone. new Function(source) still compiles source as the body of an anonymous function. A SyntaxError still throws when the grammar fails. The body never runs. console.log stays quiet. No request leaves the machine on account of the paste.

Green means the grammar parsed under that wrapper. Green does not mean the snippet is safe. Green does not mean merge it.

Four labels people mix up in a stand-up

A ticket that says "JS is broken" is usually one of four different failures. Mixing them wastes a morning.

Syntax
The engine refused to parse the source. A missing ), an unterminated string, import inside a function body, a return in a classic script. This page answers this one.
Runtime
The file parsed. Then a name was missing, a method ran on null, or the DOM node was absent. None of that is visible here, because nothing executes.
Lint
The file parsed and ran. A linter still has opinions: ==, an unused binding, a missing radix. Take that class of complaint to the JavaScript Validator, which runs JSHint.
Types
TypeScript and JSDoc. const n: number = 1 is legal for tsc and illegal for new Function. There is no TypeScript mode on this page. Strip the types, or compile, before you paste.

The wrapper is a function body. Your file often is not.

People paste an ES module, watch the receipt go red, and argue with the banner. The failure is the wrapper.

new Function(source) compiles source as the body of an anonymous function. Function bodies allow return. Function bodies reject import and export. Node loading file.mjs, Vite bundling a component, and a classic <script src> each disagree with this wrapper in a different direction.

PasteThis page (Function)Classic <script src>ES module / Vite / node file.mjs
Missing }FailsFailsFails
import / exportFailsFailsSucceeds
Top-level returnSucceedsFails (Illegal return statement)Fails
host: string (TypeScript)FailsFailsFails until tsc or a strip plugin runs
return then a newline then { ok: true }Succeeds (returns undefined at runtime)Parses. Same runtime surprise.Parses. Same runtime surprise.

Load the ES module trap above if you want to see the import case without typing. Load Stray return to see the opposite lie: a green receipt for a snippet a classic script tag would reject.

If a real paste starts with import, leave. Run the file under Node, or take mixed languages to the Code Syntax Validator. Debating the banner on this page wastes a stand-up.

Paste the forty lines the stack named. A webpack bundle is the wrong input. The receipt reports the first parse failure, not a review of three thousand generated lines.

Back to the editor if the paste is still sitting in the clipboard.

A line break after return is legal. The object you wrote is gone.

Automatic semicolon insertion is the part of JavaScript people swear they understand until a return sits on its own line.

Legal grammar. Empty payload.
function status() {return
{ok: true}}

The grammar is fine. The Function constructor compiles it. At runtime the function returns undefined. The engine inserts a semicolon after return, then treats the braces as a block with a label ok. The object literal you thought you wrote never exists.

This page stays quiet. The JavaScript Playground, or the function running in the app, is where the surprise shows up. If the question is "why is my payload empty", a syntax checker is the wrong desk.

Load the Return ASI trap if you want the receipt in front of you while you read the next sentence. The receipt says compiled. The function still hands back nothing.

Four pastes. Four different machines.

Same forty seconds of typing. Four answers. The machine you run the file on is the one that matters, not the color of a banner in a tab.

Missing brace

Fails here
function ping(host) {if (!host) {return 'missing host';}
return host.toLowerCase();

Every engine fails. The reported line is often the next token the parser refused to reconcile, which sits below the brace you deleted. Read upward from the receipt, not downward.

ES module

Fails here
import { ping } from './net.js'
export function check(host) {return ping(host)}

Vite succeeds. node --check check.mjs succeeds. This page fails, because a function body is not a module. The file is not broken. The wrapper is the wrong shape.

Stray return

Passes here
const n = 3
return n * 2

This page succeeds. Load the same bytes with <script src="app.js"> and the browser throws Illegal return statement. A green receipt on a stray return is a warning label, not a blessing.

TypeScript

Fails here
function ping(host: string): string {return host.toLowerCase()}

tsc succeeds. A bundler with a strip plugin succeeds. new Function sees a colon in a parameter list and throws. Strip, or compile, then paste the JavaScript the engine will run.

Walk off this page when the question is not grammar

node --check file.js compiles as a script, not as a function body. Use it on a file you intend to ship as a classic script. Use node --check file.mjs for a module.

The JavaScript Validator runs JSHint. Unused bindings, ==, and a missing radix show up there. They will never show up here, because they are not parse errors.

After the receipt is green and you still cannot read the file, the JavaScript Beautifier reindents the paste. Indent first when the reported line sits far below the brace you deleted.

Need a return value, a log line, or a thrown TypeError? That is execution. Open the JavaScript Playground. Do not ask this page to grow an interpreter again.

Markup and stylesheets are different grammars. An unclosed <div> belongs on the HTML Syntax Validator. A missing brace in a rule block belongs on the CSS Syntax Validator.

The ceiling, named

The snippet never leaves the tab. Compile, the file picker, and the findings copy all run in local JavaScript. Cut the network after the page has loaded and every button still works, which is the point when the paste holds a staging URL or an access token someone left in a comment.

Questions from people who already pasted

Why a green receipt still throws in the browser, and why an import fails on a file Vite accepts.

Why does import fail here when Vite accepts the same file?

new Function compiles the paste as a function body. Function bodies reject import and export. Vite loads a module. The file is fine. The wrapper is the wrong shape. Run node --check on the .mjs, or load the ES module trap on this page to see the same red receipt without arguing about Vite.

The receipt is green. The page still throws. Why?

Green is a parse. A missing name, a call on null, or a DOM node that is not there are runtime failures. This page never runs the body, so those stay invisible. A top-level return also compiles here and then throws under a classic script tag. Open the playground when you need execution, or run the file the same way production loads it.

Did this page use to execute my paste?

Yes. An earlier build called the function after compiling it. That turned a syntax checker into an interpreter, so fetch ran and a tight loop froze the tab. The invoke is gone. Compile still uses the Function constructor. The body does not run.

Does a pass mean ESLint or JSHint would pass?

No. Unused bindings, ==, and a missing radix are lint opinions. They are not parse errors. Use the JavaScript Validator for JSHint. Use the project ESLint config for the rules the team ships with. This page will stay quiet through all of that.

Why does TypeScript fail?

A colon in a parameter list is TypeScript. new Function is JavaScript. There is no TypeScript mode. Strip the types, or run tsc, then paste the JavaScript the engine will evaluate. JSDoc comments are fine because they are comments.

The error points at the last line. The last line looks fine.

The parser reports the first token it cannot reconcile with what it has already seen. An unclosed brace, string, or template literal near the top often surfaces at the end of the file. Treat the reported line as a ceiling. Indent, then read upward. The missing brace trap on this page shows that pattern.

Is the snippet uploaded?

No. Compile, the file picker, and copy all run in the tab. No request carries the source after the page has loaded. Switch the network off and the buttons keep working, which is the point when the paste holds staging URLs or tokens left in comments.