UNPKG

node-inspector-sans-ws

Version:
916 lines (814 loc) 28.6 kB
/* * Copyright (C) 2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ function FormattedContentBuilder(content, mapping, originalOffset, formattedOffset, indentString) { this._originalContent = content; this._originalOffset = originalOffset; this._lastOriginalPosition = 0; this._formattedContent = []; this._formattedContentLength = 0; this._formattedOffset = formattedOffset; this._lastFormattedPosition = 0; this._mapping = mapping; this._lineNumber = 0; this._nestingLevel = 0; this._indentString = indentString; this._cachedIndents = {}; } FormattedContentBuilder.prototype = { addToken: function(token) { for (var i = 0; i < token.comments_before.length; ++i) this._addComment(token.comments_before[i]); while (this._lineNumber < token.line) { this._addText("\n"); this._addIndent(); this._needNewLine = false; this._lineNumber += 1; } if (this._needNewLine) { this._addText("\n"); this._addIndent(); this._needNewLine = false; } this._addMappingIfNeeded(token.pos); this._addText(this._originalContent.substring(token.pos, token.endPos)); this._lineNumber = token.endLine; }, addSpace: function() { this._addText(" "); }, addNewLine: function() { this._needNewLine = true; }, increaseNestingLevel: function() { this._nestingLevel += 1; }, decreaseNestingLevel: function() { this._nestingLevel -= 1; }, content: function() { return this._formattedContent.join(""); }, mapping: function() { return { original: this._originalPositions, formatted: this._formattedPositions }; }, _addIndent: function() { if (this._cachedIndents[this._nestingLevel]) { this._addText(this._cachedIndents[this._nestingLevel]); return; } var fullIndent = ""; for (var i = 0; i < this._nestingLevel; ++i) fullIndent += this._indentString; this._addText(fullIndent); // Cache a maximum of 20 nesting level indents. if (this._nestingLevel <= 20) this._cachedIndents[this._nestingLevel] = fullIndent; }, _addComment: function(comment) { if (this._lineNumber < comment.line) { for (var j = this._lineNumber; j < comment.line; ++j) this._addText("\n"); this._lineNumber = comment.line; this._needNewLine = false; this._addIndent(); } else this.addSpace(); this._addMappingIfNeeded(comment.pos); if (comment.type === "comment1") this._addText("//"); else this._addText("/*"); this._addText(comment.value); if (comment.type !== "comment1") { this._addText("*/"); var position; while ((position = comment.value.indexOf("\n", position + 1)) !== -1) this._lineNumber += 1; } }, _addText: function(text) { this._formattedContent.push(text); this._formattedContentLength += text.length; }, _addMappingIfNeeded: function(originalPosition) { if (originalPosition - this._lastOriginalPosition === this._formattedContentLength - this._lastFormattedPosition) return; this._mapping.original.push(this._originalOffset + originalPosition); this._lastOriginalPosition = originalPosition; this._mapping.formatted.push(this._formattedOffset + this._formattedContentLength); this._lastFormattedPosition = this._formattedContentLength; } } var tokens = [ ["EOS"], ["LPAREN", "("], ["RPAREN", ")"], ["LBRACK", "["], ["RBRACK", "]"], ["LBRACE", "{"], ["RBRACE", "}"], ["COLON", ":"], ["SEMICOLON", ";"], ["PERIOD", "."], ["CONDITIONAL", "?"], ["INC", "++"], ["DEC", "--"], ["ASSIGN", "="], ["ASSIGN_BIT_OR", "|="], ["ASSIGN_BIT_XOR", "^="], ["ASSIGN_BIT_AND", "&="], ["ASSIGN_SHL", "<<="], ["ASSIGN_SAR", ">>="], ["ASSIGN_SHR", ">>>="], ["ASSIGN_ADD", "+="], ["ASSIGN_SUB", "-="], ["ASSIGN_MUL", "*="], ["ASSIGN_DIV", "/="], ["ASSIGN_MOD", "%="], ["COMMA", ","], ["OR", "||"], ["AND", "&&"], ["BIT_OR", "|"], ["BIT_XOR", "^"], ["BIT_AND", "&"], ["SHL", "<<"], ["SAR", ">>"], ["SHR", ">>>"], ["ADD", "+"], ["SUB", "-"], ["MUL", "*"], ["DIV", "/"], ["MOD", "%"], ["EQ", "=="], ["NE", "!="], ["EQ_STRICT", "==="], ["NE_STRICT", "!=="], ["LT", "<"], ["GT", ">"], ["LTE", "<="], ["GTE", ">="], ["INSTANCEOF", "instanceof"], ["IN", "in"], ["NOT", "!"], ["BIT_NOT", "~"], ["DELETE", "delete"], ["TYPEOF", "typeof"], ["VOID", "void"], ["BREAK", "break"], ["CASE", "case"], ["CATCH", "catch"], ["CONTINUE", "continue"], ["DEBUGGER", "debugger"], ["DEFAULT", "default"], ["DO", "do"], ["ELSE", "else"], ["FINALLY", "finally"], ["FOR", "for"], ["FUNCTION", "function"], ["IF", "if"], ["NEW", "new"], ["RETURN", "return"], ["SWITCH", "switch"], ["THIS", "this"], ["THROW", "throw"], ["TRY", "try"], ["VAR", "var"], ["WHILE", "while"], ["WITH", "with"], ["NULL_LITERAL", "null"], ["TRUE_LITERAL", "true"], ["FALSE_LITERAL", "false"], ["NUMBER"], ["STRING"], ["IDENTIFIER"], ["CONST", "const"] ]; var Tokens = {}; for (var i = 0; i < tokens.length; ++i) Tokens[tokens[i][0]] = i; var TokensByValue = {}; for (var i = 0; i < tokens.length; ++i) { if (tokens[i][1]) TokensByValue[tokens[i][1]] = i; } var TokensByType = { "eof": Tokens.EOS, "name": Tokens.IDENTIFIER, "num": Tokens.NUMBER, "regexp": Tokens.DIV, "string": Tokens.STRING }; function Tokenizer(content) { this._readNextToken = parse.tokenizer(content); this._state = this._readNextToken.context(); } Tokenizer.prototype = { content: function() { return this._state.text; }, next: function(forceRegexp) { var uglifyToken = this._readNextToken(forceRegexp); uglifyToken.endPos = this._state.pos; uglifyToken.endLine = this._state.line; uglifyToken.token = this._convertUglifyToken(uglifyToken); return uglifyToken; }, _convertUglifyToken: function(uglifyToken) { var token = TokensByType[uglifyToken.type]; if (typeof token === "number") return token; token = TokensByValue[uglifyToken.value]; if (typeof token === "number") return token; throw "Unknown token type " + uglifyToken.type; } } function JavaScriptFormatter(tokenizer, builder) { this._tokenizer = tokenizer; this._builder = builder; this._token = null; this._nextToken = this._tokenizer.next(); } JavaScriptFormatter.prototype = { format: function() { this._parseSourceElements(Tokens.EOS); this._consume(Tokens.EOS); }, _peek: function() { return this._nextToken.token; }, _next: function() { if (this._token && this._token.token === Tokens.EOS) throw "Unexpected EOS token"; this._builder.addToken(this._nextToken); this._token = this._nextToken; this._nextToken = this._tokenizer.next(this._forceRegexp); this._forceRegexp = false; return this._token.token; }, _consume: function(token) { var next = this._next(); if (next !== token) throw "Unexpected token in consume: expected " + token + ", actual " + next; }, _expect: function(token) { var next = this._next(); if (next !== token) throw "Unexpected token: expected " + token + ", actual " + next; }, _expectSemicolon: function() { if (this._peek() === Tokens.SEMICOLON) this._consume(Tokens.SEMICOLON); }, _hasLineTerminatorBeforeNext: function() { return this._nextToken.nlb; }, _parseSourceElements: function(endToken) { while (this._peek() !== endToken) { this._parseStatement(); this._builder.addNewLine(); } }, _parseStatementOrBlock: function() { if (this._peek() === Tokens.LBRACE) { this._builder.addSpace(); this._parseBlock(); return true; } this._builder.addNewLine(); this._builder.increaseNestingLevel(); this._parseStatement(); this._builder.decreaseNestingLevel(); }, _parseStatement: function() { switch (this._peek()) { case Tokens.LBRACE: return this._parseBlock(); case Tokens.CONST: case Tokens.VAR: return this._parseVariableStatement(); case Tokens.SEMICOLON: return this._next(); case Tokens.IF: return this._parseIfStatement(); case Tokens.DO: return this._parseDoWhileStatement(); case Tokens.WHILE: return this._parseWhileStatement(); case Tokens.FOR: return this._parseForStatement(); case Tokens.CONTINUE: return this._parseContinueStatement(); case Tokens.BREAK: return this._parseBreakStatement(); case Tokens.RETURN: return this._parseReturnStatement(); case Tokens.WITH: return this._parseWithStatement(); case Tokens.SWITCH: return this._parseSwitchStatement(); case Tokens.THROW: return this._parseThrowStatement(); case Tokens.TRY: return this._parseTryStatement(); case Tokens.FUNCTION: return this._parseFunctionDeclaration(); case Tokens.DEBUGGER: return this._parseDebuggerStatement(); default: return this._parseExpressionOrLabelledStatement(); } }, _parseFunctionDeclaration: function() { this._expect(Tokens.FUNCTION); this._builder.addSpace(); this._expect(Tokens.IDENTIFIER); this._parseFunctionLiteral() }, _parseBlock: function() { this._expect(Tokens.LBRACE); this._builder.addNewLine(); this._builder.increaseNestingLevel(); while (this._peek() !== Tokens.RBRACE) { this._parseStatement(); this._builder.addNewLine(); } this._builder.decreaseNestingLevel(); this._expect(Tokens.RBRACE); }, _parseVariableStatement: function() { this._parseVariableDeclarations(); this._expectSemicolon(); }, _parseVariableDeclarations: function() { if (this._peek() === Tokens.VAR) this._consume(Tokens.VAR); else this._consume(Tokens.CONST) this._builder.addSpace(); var isFirstVariable = true; do { if (!isFirstVariable) { this._consume(Tokens.COMMA); this._builder.addSpace(); } isFirstVariable = false; this._expect(Tokens.IDENTIFIER); if (this._peek() === Tokens.ASSIGN) { this._builder.addSpace(); this._consume(Tokens.ASSIGN); this._builder.addSpace(); this._parseAssignmentExpression(); } } while (this._peek() === Tokens.COMMA); }, _parseExpressionOrLabelledStatement: function() { this._parseExpression(); if (this._peek() === Tokens.COLON) { this._expect(Tokens.COLON); this._builder.addSpace(); this._parseStatement(); } this._expectSemicolon(); }, _parseIfStatement: function() { this._expect(Tokens.IF); this._builder.addSpace(); this._expect(Tokens.LPAREN); this._parseExpression(); this._expect(Tokens.RPAREN); var isBlock = this._parseStatementOrBlock(); if (this._peek() === Tokens.ELSE) { if (isBlock) this._builder.addSpace(); else this._builder.addNewLine(); this._next(); if (this._peek() === Tokens.IF) { this._builder.addSpace(); this._parseStatement(); } else this._parseStatementOrBlock(); } }, _parseContinueStatement: function() { this._expect(Tokens.CONTINUE); var token = this._peek(); if (!this._hasLineTerminatorBeforeNext() && token !== Tokens.SEMICOLON && token !== Tokens.RBRACE && token !== Tokens.EOS) { this._builder.addSpace(); this._expect(Tokens.IDENTIFIER); } this._expectSemicolon(); }, _parseBreakStatement: function() { this._expect(Tokens.BREAK); var token = this._peek(); if (!this._hasLineTerminatorBeforeNext() && token !== Tokens.SEMICOLON && token !== Tokens.RBRACE && token !== Tokens.EOS) { this._builder.addSpace(); this._expect(Tokens.IDENTIFIER); } this._expectSemicolon(); }, _parseReturnStatement: function() { this._expect(Tokens.RETURN); var token = this._peek(); if (!this._hasLineTerminatorBeforeNext() && token !== Tokens.SEMICOLON && token !== Tokens.RBRACE && token !== Tokens.EOS) { this._builder.addSpace(); this._parseExpression(); } this._expectSemicolon(); }, _parseWithStatement: function() { this._expect(Tokens.WITH); this._builder.addSpace(); this._expect(Tokens.LPAREN); this._parseExpression(); this._expect(Tokens.RPAREN); this._parseStatementOrBlock(); }, _parseCaseClause: function() { if (this._peek() === Tokens.CASE) { this._expect(Tokens.CASE); this._builder.addSpace(); this._parseExpression(); } else this._expect(Tokens.DEFAULT); this._expect(Tokens.COLON); this._builder.addNewLine(); this._builder.increaseNestingLevel(); while (this._peek() !== Tokens.CASE && this._peek() !== Tokens.DEFAULT && this._peek() !== Tokens.RBRACE) { this._parseStatement(); this._builder.addNewLine(); } this._builder.decreaseNestingLevel(); }, _parseSwitchStatement: function() { this._expect(Tokens.SWITCH); this._builder.addSpace(); this._expect(Tokens.LPAREN); this._parseExpression(); this._expect(Tokens.RPAREN); this._builder.addSpace(); this._expect(Tokens.LBRACE); this._builder.addNewLine(); this._builder.increaseNestingLevel(); while (this._peek() !== Tokens.RBRACE) this._parseCaseClause(); this._builder.decreaseNestingLevel(); this._expect(Tokens.RBRACE); }, _parseThrowStatement: function() { this._expect(Tokens.THROW); this._builder.addSpace(); this._parseExpression(); this._expectSemicolon(); }, _parseTryStatement: function() { this._expect(Tokens.TRY); this._builder.addSpace(); this._parseBlock(); var token = this._peek(); if (token === Tokens.CATCH) { this._builder.addSpace(); this._consume(Tokens.CATCH); this._builder.addSpace(); this._expect(Tokens.LPAREN); this._expect(Tokens.IDENTIFIER); this._expect(Tokens.RPAREN); this._builder.addSpace(); this._parseBlock(); token = this._peek(); } if (token === Tokens.FINALLY) { this._consume(Tokens.FINALLY); this._builder.addSpace(); this._parseBlock(); } }, _parseDoWhileStatement: function() { this._expect(Tokens.DO); var isBlock = this._parseStatementOrBlock(); if (isBlock) this._builder.addSpace(); else this._builder.addNewLine(); this._expect(Tokens.WHILE); this._builder.addSpace(); this._expect(Tokens.LPAREN); this._parseExpression(); this._expect(Tokens.RPAREN); this._expectSemicolon(); }, _parseWhileStatement: function() { this._expect(Tokens.WHILE); this._builder.addSpace(); this._expect(Tokens.LPAREN); this._parseExpression(); this._expect(Tokens.RPAREN); this._parseStatementOrBlock(); }, _parseForStatement: function() { this._expect(Tokens.FOR); this._builder.addSpace(); this._expect(Tokens.LPAREN); if (this._peek() !== Tokens.SEMICOLON) { if (this._peek() === Tokens.VAR || this._peek() === Tokens.CONST) { this._parseVariableDeclarations(); if (this._peek() === Tokens.IN) { this._builder.addSpace(); this._consume(Tokens.IN); this._builder.addSpace(); this._parseExpression(); } } else this._parseExpression(); } if (this._peek() !== Tokens.RPAREN) { this._expect(Tokens.SEMICOLON); this._builder.addSpace(); if (this._peek() !== Tokens.SEMICOLON) this._parseExpression(); this._expect(Tokens.SEMICOLON); this._builder.addSpace(); if (this._peek() !== Tokens.RPAREN) this._parseExpression(); } this._expect(Tokens.RPAREN); this._parseStatementOrBlock(); }, _parseExpression: function() { this._parseAssignmentExpression(); while (this._peek() === Tokens.COMMA) { this._expect(Tokens.COMMA); this._builder.addSpace(); this._parseAssignmentExpression(); } }, _parseAssignmentExpression: function() { this._parseConditionalExpression(); var token = this._peek(); if (Tokens.ASSIGN <= token && token <= Tokens.ASSIGN_MOD) { this._builder.addSpace(); this._next(); this._builder.addSpace(); this._parseAssignmentExpression(); } }, _parseConditionalExpression: function() { this._parseBinaryExpression(); if (this._peek() === Tokens.CONDITIONAL) { this._builder.addSpace(); this._consume(Tokens.CONDITIONAL); this._builder.addSpace(); this._parseAssignmentExpression(); this._builder.addSpace(); this._expect(Tokens.COLON); this._builder.addSpace(); this._parseAssignmentExpression(); } }, _parseBinaryExpression: function() { this._parseUnaryExpression(); var token = this._peek(); while (Tokens.OR <= token && token <= Tokens.IN) { this._builder.addSpace(); this._next(); this._builder.addSpace(); this._parseBinaryExpression(); token = this._peek(); } }, _parseUnaryExpression: function() { var token = this._peek(); if ((Tokens.NOT <= token && token <= Tokens.VOID) || token === Tokens.ADD || token === Tokens.SUB || token === Tokens.INC || token === Tokens.DEC) { this._next(); if (token === Tokens.DELETE || token === Tokens.TYPEOF || token === Tokens.VOID) this._builder.addSpace(); this._parseUnaryExpression(); } else return this._parsePostfixExpression(); }, _parsePostfixExpression: function() { this._parseLeftHandSideExpression(); var token = this._peek(); if (!this._hasLineTerminatorBeforeNext() && (token === Tokens.INC || token === Tokens.DEC)) this._next(); }, _parseLeftHandSideExpression: function() { if (this._peek() === Tokens.NEW) this._parseNewExpression(); else this._parseMemberExpression(); while (true) { switch (this._peek()) { case Tokens.LBRACK: this._consume(Tokens.LBRACK); this._parseExpression(); this._expect(Tokens.RBRACK); break; case Tokens.LPAREN: this._parseArguments(); break; case Tokens.PERIOD: this._consume(Tokens.PERIOD); this._expect(Tokens.IDENTIFIER); break; default: return; } } }, _parseNewExpression: function() { this._expect(Tokens.NEW); this._builder.addSpace(); if (this._peek() === Tokens.NEW) this._parseNewExpression(); else this._parseMemberExpression(); }, _parseMemberExpression: function() { if (this._peek() === Tokens.FUNCTION) { this._expect(Tokens.FUNCTION); if (this._peek() === Tokens.IDENTIFIER) { this._builder.addSpace(); this._expect(Tokens.IDENTIFIER); } this._parseFunctionLiteral(); } else this._parsePrimaryExpression(); while (true) { switch (this._peek()) { case Tokens.LBRACK: this._consume(Tokens.LBRACK); this._parseExpression(); this._expect(Tokens.RBRACK); break; case Tokens.PERIOD: this._consume(Tokens.PERIOD); this._expect(Tokens.IDENTIFIER); break; case Tokens.LPAREN: this._parseArguments(); break; default: return; } } }, _parseDebuggerStatement: function() { this._expect(Tokens.DEBUGGER); this._expectSemicolon(); }, _parsePrimaryExpression: function() { switch (this._peek()) { case Tokens.THIS: return this._consume(Tokens.THIS); case Tokens.NULL_LITERAL: return this._consume(Tokens.NULL_LITERAL); case Tokens.TRUE_LITERAL: return this._consume(Tokens.TRUE_LITERAL); case Tokens.FALSE_LITERAL: return this._consume(Tokens.FALSE_LITERAL); case Tokens.IDENTIFIER: return this._consume(Tokens.IDENTIFIER); case Tokens.NUMBER: return this._consume(Tokens.NUMBER); case Tokens.STRING: return this._consume(Tokens.STRING); case Tokens.ASSIGN_DIV: return this._parseRegExpLiteral(); case Tokens.DIV: return this._parseRegExpLiteral(); case Tokens.LBRACK: return this._parseArrayLiteral(); case Tokens.LBRACE: return this._parseObjectLiteral(); case Tokens.LPAREN: this._consume(Tokens.LPAREN); this._parseExpression(); this._expect(Tokens.RPAREN); return; default: return this._next(); } }, _parseArrayLiteral: function() { this._expect(Tokens.LBRACK); this._builder.increaseNestingLevel(); while (this._peek() !== Tokens.RBRACK) { if (this._peek() !== Tokens.COMMA) this._parseAssignmentExpression(); if (this._peek() !== Tokens.RBRACK) { this._expect(Tokens.COMMA); this._builder.addSpace(); } } this._builder.decreaseNestingLevel(); this._expect(Tokens.RBRACK); }, _parseObjectLiteralGetSet: function() { var token = this._peek(); if (token === Tokens.IDENTIFIER || token === Tokens.NUMBER || token === Tokens.STRING || Tokens.DELETE <= token && token <= Tokens.FALSE_LITERAL || token === Tokens.INSTANCEOF || token === Tokens.IN || token === Tokens.CONST) { this._next(); this._parseFunctionLiteral(); } }, _parseObjectLiteral: function() { this._expect(Tokens.LBRACE); this._builder.increaseNestingLevel(); while (this._peek() !== Tokens.RBRACE) { var token = this._peek(); switch (token) { case Tokens.IDENTIFIER: this._consume(Tokens.IDENTIFIER); var name = this._token.value; if ((name === "get" || name === "set") && this._peek() !== Tokens.COLON) { this._builder.addSpace(); this._parseObjectLiteralGetSet(); if (this._peek() !== Tokens.RBRACE) { this._expect(Tokens.COMMA); } continue; } break; case Tokens.STRING: this._consume(Tokens.STRING); break; case Tokens.NUMBER: this._consume(Tokens.NUMBER); break; default: this._next(); } this._expect(Tokens.COLON); this._builder.addSpace(); this._parseAssignmentExpression(); if (this._peek() !== Tokens.RBRACE) { this._expect(Tokens.COMMA); } } this._builder.decreaseNestingLevel(); this._expect(Tokens.RBRACE); }, _parseRegExpLiteral: function() { if (this._nextToken.type === "regexp") this._next(); else { this._forceRegexp = true; this._next(); } }, _parseArguments: function() { this._expect(Tokens.LPAREN); var done = (this._peek() === Tokens.RPAREN); while (!done) { this._parseAssignmentExpression(); done = (this._peek() === Tokens.RPAREN); if (!done) { this._expect(Tokens.COMMA); this._builder.addSpace(); } } this._expect(Tokens.RPAREN); }, _parseFunctionLiteral: function() { this._expect(Tokens.LPAREN); var done = (this._peek() === Tokens.RPAREN); while (!done) { this._expect(Tokens.IDENTIFIER); done = (this._peek() === Tokens.RPAREN); if (!done) { this._expect(Tokens.COMMA); this._builder.addSpace(); } } this._expect(Tokens.RPAREN); this._builder.addSpace(); this._expect(Tokens.LBRACE); this._builder.addNewLine(); this._builder.increaseNestingLevel(); this._parseSourceElements(Tokens.RBRACE); this._builder.decreaseNestingLevel(); this._expect(Tokens.RBRACE); } }