From e4da8cfea56b658d874e603c05f4a57b9a096786 Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Sun, 1 May 2016 18:44:38 -0700 Subject: [PATCH 01/12] Use the standard newline function. --- packages/babel-generator/src/generators/expressions.js | 2 +- packages/babel-generator/src/generators/statements.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/babel-generator/src/generators/expressions.js b/packages/babel-generator/src/generators/expressions.js index aaecc7282f..36f0485a91 100644 --- a/packages/babel-generator/src/generators/expressions.js +++ b/packages/babel-generator/src/generators/expressions.js @@ -88,7 +88,7 @@ export function Decorator(node: Object) { function commaSeparatorNewline() { this.token(","); - this.push("\n"); + this.newline(); } export function CallExpression(node: Object) { diff --git a/packages/babel-generator/src/generators/statements.js b/packages/babel-generator/src/generators/statements.js index 9cfeab8d26..38044cacbe 100644 --- a/packages/babel-generator/src/generators/statements.js +++ b/packages/babel-generator/src/generators/statements.js @@ -208,14 +208,14 @@ export function DebuggerStatement() { function variableDeclarationIdent() { // "let " or "var " indentation. this.token(","); - this.push("\n"); + this.newline(); for (let i = 0; i < 4; i++) this.push(" "); } function constDeclarationIdent() { // "const " indentation. this.token(","); - this.push("\n"); + this.newline(); for (let i = 0; i < 6; i++) this.push(" "); } From 177c092496ab6ff46b5cd3702ad1798a06aa74c1 Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Sat, 2 Jul 2016 12:42:15 -0700 Subject: [PATCH 02/12] Remove sideeffectful position mutation. --- packages/babel-generator/src/buffer.js | 2 +- packages/babel-generator/src/index.js | 2 +- packages/babel-generator/src/source-map.js | 7 ++----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/babel-generator/src/buffer.js b/packages/babel-generator/src/buffer.js index 65b35ce16d..750ecac11e 100644 --- a/packages/babel-generator/src/buffer.js +++ b/packages/babel-generator/src/buffer.js @@ -333,7 +333,7 @@ export default class Buffer { } // If there the line is ending, adding a new mapping marker is redundant - if (this.opts.sourceMaps && str[0] !== "\n") this.map.mark(this._sourcePosition); + if (this.opts.sourceMaps && str[0] !== "\n") this.map.mark(this.position, this._sourcePosition); // this.position.push(str); diff --git a/packages/babel-generator/src/index.js b/packages/babel-generator/src/index.js index 4254d8bdf9..f13bec1764 100644 --- a/packages/babel-generator/src/index.js +++ b/packages/babel-generator/src/index.js @@ -31,7 +31,7 @@ class Generator extends Printer { this._inForStatementInitCounter = 0; this.whitespace = new Whitespace(tokens); - this.map = new SourceMap(position, opts, code); + this.map = new SourceMap(opts, code); } format: { diff --git a/packages/babel-generator/src/source-map.js b/packages/babel-generator/src/source-map.js index ca23337e7e..5987e75c44 100644 --- a/packages/babel-generator/src/source-map.js +++ b/packages/babel-generator/src/source-map.js @@ -5,8 +5,7 @@ import sourceMap from "source-map"; */ export default class SourceMap { - constructor(position, opts, code) { - this.position = position; + constructor(opts, code) { this.opts = opts; this.last = {generated: {}, original: {}}; @@ -46,12 +45,10 @@ export default class SourceMap { * values to insert a mapping to nothing. */ - mark(sourcePos: Object) { + mark(position, sourcePos: Object) { let map = this.map; if (!map) return; // no source map - let position = this.position; - // Adding an empty mapping at the start of a generated line just clutters the map. if (this._lastGenLine !== position.line && sourcePos.line === null) return; From 3680d10b6f5dcf28c67fba0e3d7f9fd2689ccc90 Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Sat, 2 Jul 2016 13:22:52 -0700 Subject: [PATCH 03/12] Centralize position tracking into buffer. --- packages/babel-generator/src/buffer.js | 24 +++++++++++++++--------- packages/babel-generator/src/index.js | 7 +------ packages/babel-generator/src/printer.js | 3 +-- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/babel-generator/src/buffer.js b/packages/babel-generator/src/buffer.js index 750ecac11e..801042dfeb 100644 --- a/packages/babel-generator/src/buffer.js +++ b/packages/babel-generator/src/buffer.js @@ -1,4 +1,4 @@ -import type Position from "./position"; +import Position from "./position"; import repeat from "lodash/repeat"; import trimEnd from "lodash/trimEnd"; @@ -7,10 +7,10 @@ import trimEnd from "lodash/trimEnd"; */ export default class Buffer { - constructor(position: Position, format: Object) { + constructor(format: Object) { this.printedCommentStarts = {}; this.parenPushNewlineState = null; - this.position = position; + this._position = new Position(); this._indent = format.indent.base; this.format = format; this.buf = ""; @@ -44,7 +44,7 @@ export default class Buffer { catchUp(node: Object) { // catch up to this nodes newline if we're behind if (node.loc && this.format.retainLines && this.buf) { - while (this.position.line < node.loc.start.line) { + while (this.getCurrentLine() < node.loc.start.line) { this.push("\n"); } } @@ -164,7 +164,6 @@ export default class Buffer { this.push(str); } - /** * Remove the last character. */ @@ -178,7 +177,7 @@ export default class Buffer { if (!this.endsWith(cha)) return; this.buf = this.buf.slice(0, -1); this.last = this.buf[this.buf.length - 1]; - this.position.unshift(cha); + this._position.unshift(cha); } /** @@ -260,7 +259,7 @@ export default class Buffer { let toRemove = this.buf.slice(lastNewlineIndex + 1); this.buf = this.buf.substring(0, lastNewlineIndex + 1); this.last = "\n"; - this.position.unshift(toRemove); + this._position.unshift(toRemove); } } @@ -333,10 +332,10 @@ export default class Buffer { } // If there the line is ending, adding a new mapping marker is redundant - if (this.opts.sourceMaps && str[0] !== "\n") this.map.mark(this.position, this._sourcePosition); + if (this.opts.sourceMaps && str[0] !== "\n") this.map.mark(this._position, this._sourcePosition); // - this.position.push(str); + this._position.push(str); this.buf += str; this.last = str[str.length - 1]; @@ -358,4 +357,11 @@ export default class Buffer { } } + getCurrentColumn() { + return this._position.column; + } + + getCurrentLine() { + return this._position.line; + } } diff --git a/packages/babel-generator/src/index.js b/packages/babel-generator/src/index.js index f13bec1764..ffc9faca04 100644 --- a/packages/babel-generator/src/index.js +++ b/packages/babel-generator/src/index.js @@ -1,7 +1,6 @@ import detectIndent from "detect-indent"; import Whitespace from "./whitespace"; import SourceMap from "./source-map"; -import Position from "./position"; import * as messages from "babel-messages"; import Printer from "./printer"; @@ -18,12 +17,9 @@ class Generator extends Printer { let tokens = ast.tokens || []; let format = Generator.normalizeOptions(code, opts, tokens); - let position = new Position; - - super(position, format); + super(format); this.comments = comments; - this.position = position; this.tokens = tokens; this.format = format; this.opts = opts; @@ -54,7 +50,6 @@ class Generator extends Printer { auxiliaryCommentBefore: string; auxiliaryCommentAfter: string; whitespace: Whitespace; - position: Position; map: SourceMap; comments: Array; tokens: Array; diff --git a/packages/babel-generator/src/printer.js b/packages/babel-generator/src/printer.js index 98690a3468..79fcb230fa 100644 --- a/packages/babel-generator/src/printer.js +++ b/packages/babel-generator/src/printer.js @@ -272,7 +272,6 @@ export default class Printer extends Buffer { if (!this.endsWith(["[", "{"])) this.space(); - let column = this.position.column; let val = this.generateComment(comment); // @@ -283,7 +282,7 @@ export default class Printer extends Buffer { val = val.replace(newlineRegex, "\n"); } - let indent = Math.max(this.indentSize(), column); + let indent = Math.max(this.indentSize(), this.getCurrentColumn()); val = val.replace(/\n/g, `\n${repeat(" ", indent)}`); } From d6b1e36d4908ca30f9f5d3a527c9c5741aefd424 Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Sat, 2 Jul 2016 15:31:30 -0700 Subject: [PATCH 04/12] Make the 'catchUp' call implicit to source location updates. --- packages/babel-generator/src/buffer.js | 14 ++++++-------- packages/babel-generator/src/printer.js | 6 +----- .../expected.js | 4 +++- .../return-with-retainlines-option/expected.js | 7 ++++--- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/packages/babel-generator/src/buffer.js b/packages/babel-generator/src/buffer.js index 801042dfeb..a5fc0e432c 100644 --- a/packages/babel-generator/src/buffer.js +++ b/packages/babel-generator/src/buffer.js @@ -37,14 +37,10 @@ export default class Buffer { buf: string; last: string; - /** - * Description - */ - - catchUp(node: Object) { + _catchUp(){ // catch up to this nodes newline if we're behind - if (node.loc && this.format.retainLines && this.buf) { - while (this.getCurrentLine() < node.loc.start.line) { + if (this.format.retainLines && this._sourcePosition.line !== null) { + while (this.getCurrentLine() < this._sourcePosition.line) { this.push("\n"); } } @@ -276,6 +272,8 @@ export default class Buffer { this._sourcePosition.line = pos ? pos.line : null; this._sourcePosition.column = pos ? pos.column : null; this._sourcePosition.filename = loc && loc.filename || null; + + this._catchUp(); } /** @@ -283,7 +281,7 @@ export default class Buffer { */ withSource(prop: string, loc: Location, cb: () => void) { - if (!this.opts.sourceMaps) return cb(); + if (!this.opts.sourceMaps && !this.format.retainLines) return cb(); // Use the call stack to manage a stack of "source location" data. let originalLine = this._sourcePosition.line; diff --git a/packages/babel-generator/src/printer.js b/packages/babel-generator/src/printer.js index 79fcb230fa..f14ca8f99e 100644 --- a/packages/babel-generator/src/printer.js +++ b/packages/babel-generator/src/printer.js @@ -45,8 +45,6 @@ export default class Printer extends Buffer { this.printLeadingComments(node, parent); - this.catchUp(node); - this._printNewline(true, node, parent, opts); if (opts.before) opts.before(); @@ -264,9 +262,7 @@ export default class Printer extends Buffer { } // Exclude comments from source mappings since they will only clutter things. - this.withSource(null, null, () => { - this.catchUp(comment); - + this.withSource("start", comment.loc, () => { // whitespace before this.newline(this.whitespace.getNewlinesBefore(comment)); diff --git a/packages/babel-generator/test/fixtures/edgecase/return-with-retainlines-and-compact-option/expected.js b/packages/babel-generator/test/fixtures/edgecase/return-with-retainlines-and-compact-option/expected.js index 7441245e8e..d13817e5aa 100644 --- a/packages/babel-generator/test/fixtures/edgecase/return-with-retainlines-and-compact-option/expected.js +++ b/packages/babel-generator/test/fixtures/edgecase/return-with-retainlines-and-compact-option/expected.js @@ -1,4 +1,6 @@ function foo(l){ return( -l);} +l); + +} diff --git a/packages/babel-generator/test/fixtures/edgecase/return-with-retainlines-option/expected.js b/packages/babel-generator/test/fixtures/edgecase/return-with-retainlines-option/expected.js index cc911760dc..fd1cba7b14 100644 --- a/packages/babel-generator/test/fixtures/edgecase/return-with-retainlines-option/expected.js +++ b/packages/babel-generator/test/fixtures/edgecase/return-with-retainlines-option/expected.js @@ -1,10 +1,11 @@ function foo(l) { return ( - l);} - + l); +} function foo() { return ( 1 && 2 || - 3);} + 3); +} From 80cd3ca331a796b2f560ec703ac3aa1ffc4ed25a Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Sat, 2 Jul 2016 15:36:12 -0700 Subject: [PATCH 05/12] Drop one usage of removeLast. --- packages/babel-generator/src/buffer.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/babel-generator/src/buffer.js b/packages/babel-generator/src/buffer.js index a5fc0e432c..bd7ab81b0f 100644 --- a/packages/babel-generator/src/buffer.js +++ b/packages/babel-generator/src/buffer.js @@ -238,7 +238,6 @@ export default class Buffer { this.removeLast("\n"); } - this.removeLast(" "); this._removeSpacesAfterLastNewline(); for (let j = 0; j < i; j++) { this.push("\n"); @@ -250,12 +249,13 @@ export default class Buffer { */ _removeSpacesAfterLastNewline() { - let lastNewlineIndex = this.buf.lastIndexOf("\n"); - if (lastNewlineIndex >= 0 && this.get().length <= lastNewlineIndex) { - let toRemove = this.buf.slice(lastNewlineIndex + 1); - this.buf = this.buf.substring(0, lastNewlineIndex + 1); - this.last = "\n"; - this._position.unshift(toRemove); + const originalBuf = this.buf; + this.buf = this.buf.replace(/[ \t]+$/, ""); + + if (originalBuf.length !== this.buf.length){ + const removed = originalBuf.slice(this.buf.length); + this._position.unshift(removed); + this.last = this.buf[this.buf.length - 1]; } } From 578f48134b4113fef6040ec779efd6548b1482ef Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Tue, 26 Apr 2016 09:22:27 -0700 Subject: [PATCH 06/12] Remove removeLast usage. --- packages/babel-generator/src/buffer.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/babel-generator/src/buffer.js b/packages/babel-generator/src/buffer.js index bd7ab81b0f..3edee6eeec 100644 --- a/packages/babel-generator/src/buffer.js +++ b/packages/babel-generator/src/buffer.js @@ -103,7 +103,8 @@ export default class Buffer { */ rightBrace() { - this.newline(true); + if (!this.endsWith("\n")) this.newline(); + if (this.format.minified && !this._lastPrintedIsEmptyStatement) { this._removeLast(";"); } @@ -212,10 +213,9 @@ export default class Buffer { /** * Add a newline (or many newlines), maintaining formatting. - * Strips multiple newlines if removeLast is true. */ - newline(i?: boolean | number, removeLast?: boolean) { + newline(i?: number) { if (this.format.retainLines || this.format.compact) return; if (this.format.concise) { @@ -226,18 +226,12 @@ export default class Buffer { // never allow more than two lines if (this.endsWith("\n\n")) return; - if (typeof i === "boolean") removeLast = i; if (typeof i !== "number") i = 1; i = Math.min(2, i); if (this.endsWith("{\n") || this.endsWith(":\n")) i--; if (i <= 0) return; - // remove the last newline - if (removeLast) { - this.removeLast("\n"); - } - this._removeSpacesAfterLastNewline(); for (let j = 0; j < i; j++) { this.push("\n"); From caef91672d0e8c4f154a1cb108b505e9954c627f Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Sun, 1 May 2016 18:42:33 -0700 Subject: [PATCH 07/12] Remove unnecessary passthrough function. --- packages/babel-generator/src/buffer.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/babel-generator/src/buffer.js b/packages/babel-generator/src/buffer.js index 3edee6eeec..2f778535d8 100644 --- a/packages/babel-generator/src/buffer.js +++ b/packages/babel-generator/src/buffer.js @@ -106,7 +106,7 @@ export default class Buffer { if (!this.endsWith("\n")) this.newline(); if (this.format.minified && !this._lastPrintedIsEmptyStatement) { - this._removeLast(";"); + this.removeLast(";"); } this.token("}"); } @@ -166,11 +166,6 @@ export default class Buffer { */ removeLast(cha: string) { - if (this.format.compact) return; - return this._removeLast(cha); - } - - _removeLast(cha: string) { if (!this.endsWith(cha)) return; this.buf = this.buf.slice(0, -1); this.last = this.buf[this.buf.length - 1]; From f908f3fc88dd56910b5f42f201ca61145f1f69a5 Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Sun, 3 Jul 2016 20:35:57 -0700 Subject: [PATCH 08/12] Use 'push' for all cases. --- packages/babel-generator/src/buffer.js | 4 ++-- packages/babel-generator/src/generators/statements.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/babel-generator/src/buffer.js b/packages/babel-generator/src/buffer.js index 2f778535d8..204641d60d 100644 --- a/packages/babel-generator/src/buffer.js +++ b/packages/babel-generator/src/buffer.js @@ -124,10 +124,10 @@ export default class Buffer { * Add a space to the buffer unless it is compact. */ - space() { + space(force: boolean = false) { if (this.format.compact) return; - if (this.buf && !this.endsWith(" ") && !this.endsWith("\n")) { + if ((this.buf && !this.endsWith(" ") && !this.endsWith("\n")) || force) { this.push(" "); } } diff --git a/packages/babel-generator/src/generators/statements.js b/packages/babel-generator/src/generators/statements.js index 38044cacbe..e4aa15fd50 100644 --- a/packages/babel-generator/src/generators/statements.js +++ b/packages/babel-generator/src/generators/statements.js @@ -209,14 +209,14 @@ function variableDeclarationIdent() { // "let " or "var " indentation. this.token(","); this.newline(); - for (let i = 0; i < 4; i++) this.push(" "); + for (let i = 0; i < 4; i++) this.space(true); } function constDeclarationIdent() { // "const " indentation. this.token(","); this.newline(); - for (let i = 0; i < 6; i++) this.push(" "); + for (let i = 0; i < 6; i++) this.space(true); } export function VariableDeclaration(node: Object, parent: Object) { From abb9618e8c43fc7baebefd4d635014c4e5427305 Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Tue, 5 Jul 2016 18:09:54 -0700 Subject: [PATCH 09/12] Drop array support from endsWith. --- packages/babel-generator/src/buffer.js | 2 -- packages/babel-generator/src/printer.js | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/babel-generator/src/buffer.js b/packages/babel-generator/src/buffer.js index 204641d60d..0b691e4be0 100644 --- a/packages/babel-generator/src/buffer.js +++ b/packages/babel-generator/src/buffer.js @@ -335,8 +335,6 @@ export default class Buffer { */ endsWith(str: string): boolean { - if (Array.isArray(str)) return str.some((s) => this.endsWith(s)); - if (str.length === 1) { return this.last === str; } else { diff --git a/packages/babel-generator/src/printer.js b/packages/babel-generator/src/printer.js index f14ca8f99e..3efe5437c2 100644 --- a/packages/babel-generator/src/printer.js +++ b/packages/babel-generator/src/printer.js @@ -266,7 +266,7 @@ export default class Printer extends Buffer { // whitespace before this.newline(this.whitespace.getNewlinesBefore(comment)); - if (!this.endsWith(["[", "{"])) this.space(); + if (!this.endsWith("[") && !this.endsWith("{")) this.space(); let val = this.generateComment(comment); From c5a6c5c291b0295973289c2e4a1da9ff0f389e3b Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Tue, 5 Jul 2016 20:16:12 -0700 Subject: [PATCH 10/12] Pass values directly to avoid object usage. --- packages/babel-generator/src/buffer.js | 3 ++- packages/babel-generator/src/source-map.js | 21 +++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/babel-generator/src/buffer.js b/packages/babel-generator/src/buffer.js index 0b691e4be0..d7b24a2b65 100644 --- a/packages/babel-generator/src/buffer.js +++ b/packages/babel-generator/src/buffer.js @@ -319,7 +319,8 @@ export default class Buffer { } // If there the line is ending, adding a new mapping marker is redundant - if (this.opts.sourceMaps && str[0] !== "\n") this.map.mark(this._position, this._sourcePosition); + if (this.opts.sourceMaps && str[0] !== "\n") this.map.mark(this._position, this._sourcePosition.line, + this._sourcePosition.column, this._sourcePosition.filename); // this._position.push(str); diff --git a/packages/babel-generator/src/source-map.js b/packages/babel-generator/src/source-map.js index 5987e75c44..36bfe89097 100644 --- a/packages/babel-generator/src/source-map.js +++ b/packages/babel-generator/src/source-map.js @@ -1,4 +1,5 @@ import sourceMap from "source-map"; +import type Position from "./position"; /** * Build a sourcemap. @@ -45,33 +46,33 @@ export default class SourceMap { * values to insert a mapping to nothing. */ - mark(position, sourcePos: Object) { + mark(position: Position, line: number, column: number, filename: ?string) { let map = this.map; if (!map) return; // no source map // Adding an empty mapping at the start of a generated line just clutters the map. - if (this._lastGenLine !== position.line && sourcePos.line === null) return; + if (this._lastGenLine !== position.line && line === null) return; // If this mapping points to the same source location as the last one, we can ignore it since // the previous one covers it. - if (this._lastGenLine === position.line && this._lastSourceLine === sourcePos.line && - this._lastSourceColumn === sourcePos.column) { + if (this._lastGenLine === position.line && this._lastSourceLine === line && + this._lastSourceColumn === column) { return; } this._lastGenLine = position.line; - this._lastSourceLine = sourcePos.line; - this._lastSourceColumn = sourcePos.column; + this._lastSourceLine = line; + this._lastSourceColumn = column; map.addMapping({ generated: { line: position.line, column: position.column }, - source: sourcePos.line == null ? null : sourcePos.filename || this.opts.sourceFileName, - original: sourcePos.line == null ? null : { - line: sourcePos.line, - column: sourcePos.column, + source: line == null ? null : filename || this.opts.sourceFileName, + original: line == null ? null : { + line: line, + column: column, }, }); } From cb60808500100d391326cb8d82ae9ba34a21f1bc Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Mon, 4 Jul 2016 16:21:32 -0700 Subject: [PATCH 11/12] Make buffer a property for managing the token queue. --- packages/babel-generator/src/buffer.js | 355 ++++-------------- .../babel-generator/src/generators/base.js | 2 +- packages/babel-generator/src/index.js | 11 +- packages/babel-generator/src/printer.js | 287 ++++++++++++-- 4 files changed, 343 insertions(+), 312 deletions(-) diff --git a/packages/babel-generator/src/buffer.js b/packages/babel-generator/src/buffer.js index d7b24a2b65..5bb911bbfc 100644 --- a/packages/babel-generator/src/buffer.js +++ b/packages/babel-generator/src/buffer.js @@ -1,251 +1,99 @@ import Position from "./position"; -import repeat from "lodash/repeat"; +import type SourceMap from "./source-map"; import trimEnd from "lodash/trimEnd"; /** - * Buffer for collecting generated output. + * The Buffer class exists to manage the queue of tokens being pushed onto the output string + * in such a way that the final string buffer is treated as write-only until the final .get() + * call. This allows V8 to optimize the output efficiently by not requiring it to store the + * string in contiguous memory. */ export default class Buffer { - constructor(format: Object) { - this.printedCommentStarts = {}; - this.parenPushNewlineState = null; - this._position = new Position(); - this._indent = format.indent.base; - this.format = format; - this.buf = ""; - - // Maintaining a reference to the last char in the buffer is an optimization - // to make sure that v8 doesn't "flatten" the string more often than needed - // see https://github.com/babel/babel/pull/3283 for details. - this.last = ""; - - this.map = null; - this._sourcePosition = { - line: null, - column: null, - filename: null, - }; - this._endsWithWord = false; + constructor(map: ?SourceMap) { + this._map = map; } - printedCommentStarts: Object; - parenPushNewlineState: ?Object; - position: Position; - _indent: number; - format: Object; - buf: string; - last: string; + _map: SourceMap = null; + _buf: string = ""; + _last: string = ""; + _queue: Array = []; - _catchUp(){ - // catch up to this nodes newline if we're behind - if (this.format.retainLines && this._sourcePosition.line !== null) { - while (this.getCurrentLine() < this._sourcePosition.line) { - this.push("\n"); - } - } - } + _position: Position = new Position; + _sourcePosition: Object = { + line: null, + column: null, + filename: null, + }; /** - * Get the current trimmed buffer. + * Get the final string output from the buffer, along with the sourcemap if one exists. */ - get(): string { - return trimEnd(this.buf); - } - - /** - * Get the current indent. - */ - - getIndent(): string { - if (this.format.compact || this.format.concise) { - return ""; - } else { - return repeat(this.format.indent.style, this._indent); - } - } - - /** - * Get the current indent size. - */ - - indentSize(): number { - return this.getIndent().length; - } - - /** - * Increment indent size. - */ - - indent() { - this._indent++; - } - - /** - * Decrement indent size. - */ - - dedent() { - this._indent--; - } - - /** - * Add a semicolon to the buffer. - */ - - semicolon() { - this.token(";"); - } - - /** - * Add a right brace to the buffer. - */ - - rightBrace() { - if (!this.endsWith("\n")) this.newline(); - - if (this.format.minified && !this._lastPrintedIsEmptyStatement) { - this.removeLast(";"); - } - this.token("}"); - } - - /** - * Add a keyword to the buffer. - */ - - keyword(name: string) { - this.word(name); - this.space(); - } - - /** - * Add a space to the buffer unless it is compact. - */ - - space(force: boolean = false) { - if (this.format.compact) return; - - if ((this.buf && !this.endsWith(" ") && !this.endsWith("\n")) || force) { - this.push(" "); - } - } - - /** - * Writes a token that can't be safely parsed without taking whitespace into account. - */ - - word(str: string) { - if (this._endsWithWord) this.push(" "); - - this.push(str); - this._endsWithWord = true; - } - - /** - * Writes a simple token. - */ - - token(str: string) { - // space is mandatory to avoid outputting