mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 16:58:38 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
11
devtools/shared/pretty-fast/UPGRADING.md
Normal file
11
devtools/shared/pretty-fast/UPGRADING.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# UPGRADING
|
||||
|
||||
1. `git clone https://github.com/mozilla/pretty-fast.git`
|
||||
|
||||
2. Copy `pretty-fast/pretty-fast.js` to `devtools/shared/pretty-fast/pretty-fast.js`
|
||||
|
||||
3. Copy `pretty-fast/test.js` to `devtools/shared/pretty-fast/tests/unit/test.js`
|
||||
|
||||
4. If necessary, upgrade acorn (see devtools/shared/acorn/UPGRADING.md)
|
||||
|
||||
5. Replace `acorn/dist/` with `acorn/` in pretty-fast.js.
|
||||
11
devtools/shared/pretty-fast/moz.build
Normal file
11
devtools/shared/pretty-fast/moz.build
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
|
||||
|
||||
DevToolsModules(
|
||||
'pretty-fast.js',
|
||||
)
|
||||
873
devtools/shared/pretty-fast/pretty-fast.js
Normal file
873
devtools/shared/pretty-fast/pretty-fast.js
Normal file
|
|
@ -0,0 +1,873 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2; fill-column: 80 -*- */
|
||||
/*
|
||||
* Copyright 2013 Mozilla Foundation and contributors
|
||||
* Licensed under the New BSD license. See LICENSE.md or:
|
||||
* http://opensource.org/licenses/BSD-2-Clause
|
||||
*/
|
||||
(function (root, factory) {
|
||||
"use strict";
|
||||
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(factory);
|
||||
} else if (typeof exports === "object") {
|
||||
module.exports = factory();
|
||||
} else {
|
||||
root.prettyFast = factory();
|
||||
}
|
||||
}(this, function () {
|
||||
"use strict";
|
||||
|
||||
var acorn = this.acorn || require("acorn/acorn");
|
||||
var sourceMap = this.sourceMap || require("source-map");
|
||||
var SourceNode = sourceMap.SourceNode;
|
||||
|
||||
// If any of these tokens are seen before a "[" token, we know that "[" token
|
||||
// is the start of an array literal, rather than a property access.
|
||||
//
|
||||
// The only exception is "}", which would need to be disambiguated by
|
||||
// parsing. The majority of the time, an open bracket following a closing
|
||||
// curly is going to be an array literal, so we brush the complication under
|
||||
// the rug, and handle the ambiguity by always assuming that it will be an
|
||||
// array literal.
|
||||
var PRE_ARRAY_LITERAL_TOKENS = {
|
||||
"typeof": true,
|
||||
"void": true,
|
||||
"delete": true,
|
||||
"case": true,
|
||||
"do": true,
|
||||
"=": true,
|
||||
"in": true,
|
||||
"{": true,
|
||||
"*": true,
|
||||
"/": true,
|
||||
"%": true,
|
||||
"else": true,
|
||||
";": true,
|
||||
"++": true,
|
||||
"--": true,
|
||||
"+": true,
|
||||
"-": true,
|
||||
"~": true,
|
||||
"!": true,
|
||||
":": true,
|
||||
"?": true,
|
||||
">>": true,
|
||||
">>>": true,
|
||||
"<<": true,
|
||||
"||": true,
|
||||
"&&": true,
|
||||
"<": true,
|
||||
">": true,
|
||||
"<=": true,
|
||||
">=": true,
|
||||
"instanceof": true,
|
||||
"&": true,
|
||||
"^": true,
|
||||
"|": true,
|
||||
"==": true,
|
||||
"!=": true,
|
||||
"===": true,
|
||||
"!==": true,
|
||||
",": true,
|
||||
|
||||
"}": true
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if we think that the given token starts an array literal.
|
||||
*
|
||||
* @param Object token
|
||||
* The token we want to determine if it is an array literal.
|
||||
* @param Object lastToken
|
||||
* The last token we added to the pretty printed results.
|
||||
*
|
||||
* @returns Boolean
|
||||
* True if we believe it is an array literal, false otherwise.
|
||||
*/
|
||||
function isArrayLiteral(token, lastToken) {
|
||||
if (token.type.label != "[") {
|
||||
return false;
|
||||
}
|
||||
if (!lastToken) {
|
||||
return true;
|
||||
}
|
||||
if (lastToken.type.isAssign) {
|
||||
return true;
|
||||
}
|
||||
return !!PRE_ARRAY_LITERAL_TOKENS[
|
||||
lastToken.type.keyword || lastToken.type.label
|
||||
];
|
||||
}
|
||||
|
||||
// If any of these tokens are followed by a token on a new line, we know that
|
||||
// ASI cannot happen.
|
||||
var PREVENT_ASI_AFTER_TOKENS = {
|
||||
// Binary operators
|
||||
"*": true,
|
||||
"/": true,
|
||||
"%": true,
|
||||
"+": true,
|
||||
"-": true,
|
||||
"<<": true,
|
||||
">>": true,
|
||||
">>>": true,
|
||||
"<": true,
|
||||
">": true,
|
||||
"<=": true,
|
||||
">=": true,
|
||||
"instanceof": true,
|
||||
"in": true,
|
||||
"==": true,
|
||||
"!=": true,
|
||||
"===": true,
|
||||
"!==": true,
|
||||
"&": true,
|
||||
"^": true,
|
||||
"|": true,
|
||||
"&&": true,
|
||||
"||": true,
|
||||
",": true,
|
||||
".": true,
|
||||
"=": true,
|
||||
"*=": true,
|
||||
"/=": true,
|
||||
"%=": true,
|
||||
"+=": true,
|
||||
"-=": true,
|
||||
"<<=": true,
|
||||
">>=": true,
|
||||
">>>=": true,
|
||||
"&=": true,
|
||||
"^=": true,
|
||||
"|=": true,
|
||||
// Unary operators
|
||||
"delete": true,
|
||||
"void": true,
|
||||
"typeof": true,
|
||||
"~": true,
|
||||
"!": true,
|
||||
"new": true,
|
||||
// Function calls and grouped expressions
|
||||
"(": true
|
||||
};
|
||||
|
||||
// If any of these tokens are on a line after the token before it, we know
|
||||
// that ASI cannot happen.
|
||||
var PREVENT_ASI_BEFORE_TOKENS = {
|
||||
// Binary operators
|
||||
"*": true,
|
||||
"/": true,
|
||||
"%": true,
|
||||
"<<": true,
|
||||
">>": true,
|
||||
">>>": true,
|
||||
"<": true,
|
||||
">": true,
|
||||
"<=": true,
|
||||
">=": true,
|
||||
"instanceof": true,
|
||||
"in": true,
|
||||
"==": true,
|
||||
"!=": true,
|
||||
"===": true,
|
||||
"!==": true,
|
||||
"&": true,
|
||||
"^": true,
|
||||
"|": true,
|
||||
"&&": true,
|
||||
"||": true,
|
||||
",": true,
|
||||
".": true,
|
||||
"=": true,
|
||||
"*=": true,
|
||||
"/=": true,
|
||||
"%=": true,
|
||||
"+=": true,
|
||||
"-=": true,
|
||||
"<<=": true,
|
||||
">>=": true,
|
||||
">>>=": true,
|
||||
"&=": true,
|
||||
"^=": true,
|
||||
"|=": true,
|
||||
// Function calls
|
||||
"(": true
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if Automatic Semicolon Insertion (ASI) occurs between these
|
||||
* tokens.
|
||||
*
|
||||
* @param Object token
|
||||
* The current token.
|
||||
* @param Object lastToken
|
||||
* The last token we added to the pretty printed results.
|
||||
*
|
||||
* @returns Boolean
|
||||
* True if we believe ASI occurs.
|
||||
*/
|
||||
function isASI(token, lastToken) {
|
||||
if (!lastToken) {
|
||||
return false;
|
||||
}
|
||||
if (token.loc.start.line === lastToken.loc.start.line) {
|
||||
return false;
|
||||
}
|
||||
if (PREVENT_ASI_AFTER_TOKENS[
|
||||
lastToken.type.label || lastToken.type.keyword
|
||||
]) {
|
||||
return false;
|
||||
}
|
||||
if (PREVENT_ASI_BEFORE_TOKENS[token.type.label || token.type.keyword]) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if we have encountered a getter or setter.
|
||||
*
|
||||
* @param Object token
|
||||
* The current token. If this is a getter or setter, it would be the
|
||||
* property name.
|
||||
* @param Object lastToken
|
||||
* The last token we added to the pretty printed results. If this is a
|
||||
* getter or setter, it would be the `get` or `set` keyword
|
||||
* respectively.
|
||||
* @param Array stack
|
||||
* The stack of open parens/curlies/brackets/etc.
|
||||
*
|
||||
* @returns Boolean
|
||||
* True if this is a getter or setter.
|
||||
*/
|
||||
function isGetterOrSetter(token, lastToken, stack) {
|
||||
return stack[stack.length - 1] == "{"
|
||||
&& lastToken
|
||||
&& lastToken.type.label == "name"
|
||||
&& (lastToken.value == "get" || lastToken.value == "set")
|
||||
&& token.type.label == "name";
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if we should add a newline after the given token.
|
||||
*
|
||||
* @param Object token
|
||||
* The token we are looking at.
|
||||
* @param Array stack
|
||||
* The stack of open parens/curlies/brackets/etc.
|
||||
*
|
||||
* @returns Boolean
|
||||
* True if we should add a newline.
|
||||
*/
|
||||
function isLineDelimiter(token, stack) {
|
||||
if (token.isArrayLiteral) {
|
||||
return true;
|
||||
}
|
||||
var ttl = token.type.label;
|
||||
var top = stack[stack.length - 1];
|
||||
return ttl == ";" && top != "("
|
||||
|| ttl == "{"
|
||||
|| ttl == "," && top != "("
|
||||
|| ttl == ":" && (top == "case" || top == "default");
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the necessary whitespace to the result after we have added the given
|
||||
* token.
|
||||
*
|
||||
* @param Object token
|
||||
* The token that was just added to the result.
|
||||
* @param Function write
|
||||
* The function to write to the pretty printed results.
|
||||
* @param Array stack
|
||||
* The stack of open parens/curlies/brackets/etc.
|
||||
*
|
||||
* @returns Boolean
|
||||
* Returns true if we added a newline to result, false in all other
|
||||
* cases.
|
||||
*/
|
||||
function appendNewline(token, write, stack) {
|
||||
if (isLineDelimiter(token, stack)) {
|
||||
write("\n", token.loc.start.line, token.loc.start.column);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if we need to add a space between the last token we added and
|
||||
* the token we are about to add.
|
||||
*
|
||||
* @param Object token
|
||||
* The token we are about to add to the pretty printed code.
|
||||
* @param Object lastToken
|
||||
* The last token added to the pretty printed code.
|
||||
*/
|
||||
function needsSpaceAfter(token, lastToken) {
|
||||
if (lastToken) {
|
||||
if (lastToken.type.isLoop) {
|
||||
return true;
|
||||
}
|
||||
if (lastToken.type.isAssign) {
|
||||
return true;
|
||||
}
|
||||
if (lastToken.type.binop != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var ltt = lastToken.type.label;
|
||||
if (ltt == "?") {
|
||||
return true;
|
||||
}
|
||||
if (ltt == ":") {
|
||||
return true;
|
||||
}
|
||||
if (ltt == ",") {
|
||||
return true;
|
||||
}
|
||||
if (ltt == ";") {
|
||||
return true;
|
||||
}
|
||||
|
||||
var ltk = lastToken.type.keyword;
|
||||
if (ltk != null) {
|
||||
if (ltk == "break" || ltk == "continue" || ltk == "return") {
|
||||
return token.type.label != ";";
|
||||
}
|
||||
if (ltk != "debugger"
|
||||
&& ltk != "null"
|
||||
&& ltk != "true"
|
||||
&& ltk != "false"
|
||||
&& ltk != "this"
|
||||
&& ltk != "default") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ltt == ")" && (token.type.label != ")"
|
||||
&& token.type.label != "]"
|
||||
&& token.type.label != ";"
|
||||
&& token.type.label != ","
|
||||
&& token.type.label != ".")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (token.type.isAssign) {
|
||||
return true;
|
||||
}
|
||||
if (token.type.binop != null) {
|
||||
return true;
|
||||
}
|
||||
if (token.type.label == "?") {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the required whitespace before this token, whether that is a single
|
||||
* space, newline, and/or the indent on fresh lines.
|
||||
*
|
||||
* @param Object token
|
||||
* The token we are about to add to the pretty printed code.
|
||||
* @param Object lastToken
|
||||
* The last token we added to the pretty printed code.
|
||||
* @param Boolean addedNewline
|
||||
* Whether we added a newline after adding the last token to the pretty
|
||||
* printed code.
|
||||
* @param Function write
|
||||
* The function to write pretty printed code to the result SourceNode.
|
||||
* @param Object options
|
||||
* The options object.
|
||||
* @param Number indentLevel
|
||||
* The number of indents deep we are.
|
||||
* @param Array stack
|
||||
* The stack of open curlies, brackets, etc.
|
||||
*/
|
||||
function prependWhiteSpace(token, lastToken, addedNewline, write, options,
|
||||
indentLevel, stack) {
|
||||
var ttk = token.type.keyword;
|
||||
var ttl = token.type.label;
|
||||
var newlineAdded = addedNewline;
|
||||
var ltt = lastToken ? lastToken.type.label : null;
|
||||
|
||||
// Handle whitespace and newlines after "}" here instead of in
|
||||
// `isLineDelimiter` because it is only a line delimiter some of the
|
||||
// time. For example, we don't want to put "else if" on a new line after
|
||||
// the first if's block.
|
||||
if (lastToken && ltt == "}") {
|
||||
if (ttk == "while" && stack[stack.length - 1] == "do") {
|
||||
write(" ",
|
||||
lastToken.loc.start.line,
|
||||
lastToken.loc.start.column);
|
||||
} else if (ttk == "else" ||
|
||||
ttk == "catch" ||
|
||||
ttk == "finally") {
|
||||
write(" ",
|
||||
lastToken.loc.start.line,
|
||||
lastToken.loc.start.column);
|
||||
} else if (ttl != "(" &&
|
||||
ttl != ";" &&
|
||||
ttl != "," &&
|
||||
ttl != ")" &&
|
||||
ttl != ".") {
|
||||
write("\n",
|
||||
lastToken.loc.start.line,
|
||||
lastToken.loc.start.column);
|
||||
newlineAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isGetterOrSetter(token, lastToken, stack)) {
|
||||
write(" ",
|
||||
lastToken.loc.start.line,
|
||||
lastToken.loc.start.column);
|
||||
}
|
||||
|
||||
if (ttl == ":" && stack[stack.length - 1] == "?") {
|
||||
write(" ",
|
||||
lastToken.loc.start.line,
|
||||
lastToken.loc.start.column);
|
||||
}
|
||||
|
||||
if (lastToken && ltt != "}" && ttk == "else") {
|
||||
write(" ",
|
||||
lastToken.loc.start.line,
|
||||
lastToken.loc.start.column);
|
||||
}
|
||||
|
||||
function ensureNewline() {
|
||||
if (!newlineAdded) {
|
||||
write("\n",
|
||||
lastToken.loc.start.line,
|
||||
lastToken.loc.start.column);
|
||||
newlineAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isASI(token, lastToken)) {
|
||||
ensureNewline();
|
||||
}
|
||||
|
||||
if (decrementsIndent(ttl, stack)) {
|
||||
ensureNewline();
|
||||
}
|
||||
|
||||
if (newlineAdded) {
|
||||
if (ttk == "case" || ttk == "default") {
|
||||
write(repeat(options.indent, indentLevel - 1),
|
||||
token.loc.start.line,
|
||||
token.loc.start.column);
|
||||
} else {
|
||||
write(repeat(options.indent, indentLevel),
|
||||
token.loc.start.line,
|
||||
token.loc.start.column);
|
||||
}
|
||||
} else if (needsSpaceAfter(token, lastToken)) {
|
||||
write(" ",
|
||||
lastToken.loc.start.line,
|
||||
lastToken.loc.start.column);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeat the `str` string `n` times.
|
||||
*
|
||||
* @param String str
|
||||
* The string to be repeated.
|
||||
* @param Number n
|
||||
* The number of times to repeat the string.
|
||||
*
|
||||
* @returns String
|
||||
* The repeated string.
|
||||
*/
|
||||
function repeat(str, n) {
|
||||
var result = "";
|
||||
while (n > 0) {
|
||||
if (n & 1) {
|
||||
result += str;
|
||||
}
|
||||
n >>= 1;
|
||||
str += str;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that we output the escaped character combination inside string
|
||||
* literals instead of various problematic characters.
|
||||
*/
|
||||
var sanitize = (function () {
|
||||
var escapeCharacters = {
|
||||
// Backslash
|
||||
"\\": "\\\\",
|
||||
// Newlines
|
||||
"\n": "\\n",
|
||||
// Carriage return
|
||||
"\r": "\\r",
|
||||
// Tab
|
||||
"\t": "\\t",
|
||||
// Vertical tab
|
||||
"\v": "\\v",
|
||||
// Form feed
|
||||
"\f": "\\f",
|
||||
// Null character
|
||||
"\0": "\\0",
|
||||
// Single quotes
|
||||
"'": "\\'"
|
||||
};
|
||||
|
||||
var regExpString = "("
|
||||
+ Object.keys(escapeCharacters)
|
||||
.map(function (c) { return escapeCharacters[c]; })
|
||||
.join("|")
|
||||
+ ")";
|
||||
var escapeCharactersRegExp = new RegExp(regExpString, "g");
|
||||
|
||||
return function (str) {
|
||||
return str.replace(escapeCharactersRegExp, function (_, c) {
|
||||
return escapeCharacters[c];
|
||||
});
|
||||
};
|
||||
}());
|
||||
/**
|
||||
* Add the given token to the pretty printed results.
|
||||
*
|
||||
* @param Object token
|
||||
* The token to add.
|
||||
* @param Function write
|
||||
* The function to write pretty printed code to the result SourceNode.
|
||||
*/
|
||||
function addToken(token, write) {
|
||||
if (token.type.label == "string") {
|
||||
write("'" + sanitize(token.value) + "'",
|
||||
token.loc.start.line,
|
||||
token.loc.start.column);
|
||||
} else if (token.type.label == "regexp") {
|
||||
write(String(token.value.value),
|
||||
token.loc.start.line,
|
||||
token.loc.start.column);
|
||||
} else {
|
||||
write(String(token.value != null ? token.value : token.type.label),
|
||||
token.loc.start.line,
|
||||
token.loc.start.column);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given token type belongs on the stack.
|
||||
*/
|
||||
function belongsOnStack(token) {
|
||||
var ttl = token.type.label;
|
||||
var ttk = token.type.keyword;
|
||||
return ttl == "{"
|
||||
|| ttl == "("
|
||||
|| ttl == "["
|
||||
|| ttl == "?"
|
||||
|| ttk == "do"
|
||||
|| ttk == "switch"
|
||||
|| ttk == "case"
|
||||
|| ttk == "default";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given token should cause us to pop the stack.
|
||||
*/
|
||||
function shouldStackPop(token, stack) {
|
||||
var ttl = token.type.label;
|
||||
var ttk = token.type.keyword;
|
||||
var top = stack[stack.length - 1];
|
||||
return ttl == "]"
|
||||
|| ttl == ")"
|
||||
|| ttl == "}"
|
||||
|| (ttl == ":" && (top == "case" || top == "default" || top == "?"))
|
||||
|| (ttk == "while" && top == "do");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given token type should cause us to decrement the
|
||||
* indent level.
|
||||
*/
|
||||
function decrementsIndent(tokenType, stack) {
|
||||
return tokenType == "}"
|
||||
|| (tokenType == "]" && stack[stack.length - 1] == "[\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given token should cause us to increment the indent
|
||||
* level.
|
||||
*/
|
||||
function incrementsIndent(token) {
|
||||
return token.type.label == "{"
|
||||
|| token.isArrayLiteral
|
||||
|| token.type.keyword == "switch";
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a comment to the pretty printed code.
|
||||
*
|
||||
* @param Function write
|
||||
* The function to write pretty printed code to the result SourceNode.
|
||||
* @param Number indentLevel
|
||||
* The number of indents deep we are.
|
||||
* @param Object options
|
||||
* The options object.
|
||||
* @param Boolean block
|
||||
* True if the comment is a multiline block style comment.
|
||||
* @param String text
|
||||
* The text of the comment.
|
||||
* @param Number line
|
||||
* The line number to comment appeared on.
|
||||
* @param Number column
|
||||
* The column number the comment appeared on.
|
||||
*/
|
||||
function addComment(write, indentLevel, options, block, text, line, column) {
|
||||
var indentString = repeat(options.indent, indentLevel);
|
||||
|
||||
write(indentString, line, column);
|
||||
if (block) {
|
||||
write("/*");
|
||||
write(text
|
||||
.split(new RegExp("/\n" + indentString + "/", "g"))
|
||||
.join("\n" + indentString));
|
||||
write("*/");
|
||||
} else {
|
||||
write("//");
|
||||
write(text);
|
||||
}
|
||||
write("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* The main function.
|
||||
*
|
||||
* @param String input
|
||||
* The ugly JS code we want to pretty print.
|
||||
* @param Object options
|
||||
* The options object. Provides configurability of the pretty
|
||||
* printing. Properties:
|
||||
* - url: The URL string of the ugly JS code.
|
||||
* - indent: The string to indent code by.
|
||||
*
|
||||
* @returns Object
|
||||
* An object with the following properties:
|
||||
* - code: The pretty printed code string.
|
||||
* - map: A SourceMapGenerator instance.
|
||||
*/
|
||||
return function prettyFast(input, options) {
|
||||
// The level of indents deep we are.
|
||||
var indentLevel = 0;
|
||||
|
||||
// We will accumulate the pretty printed code in this SourceNode.
|
||||
var result = new SourceNode();
|
||||
|
||||
/**
|
||||
* Write a pretty printed string to the result SourceNode.
|
||||
*
|
||||
* We buffer our writes so that we only create one mapping for each line in
|
||||
* the source map. This enhances performance by avoiding extraneous mapping
|
||||
* serialization, and flattening the tree that
|
||||
* `SourceNode#toStringWithSourceMap` will have to recursively walk. When
|
||||
* timing how long it takes to pretty print jQuery, this optimization
|
||||
* brought the time down from ~390 ms to ~190ms!
|
||||
*
|
||||
* @param String str
|
||||
* The string to be added to the result.
|
||||
* @param Number line
|
||||
* The line number the string came from in the ugly source.
|
||||
* @param Number column
|
||||
* The column number the string came from in the ugly source.
|
||||
*/
|
||||
var write = (function () {
|
||||
var buffer = [];
|
||||
var bufferLine = -1;
|
||||
var bufferColumn = -1;
|
||||
return function write(str, line, column) {
|
||||
if (line != null && bufferLine === -1) {
|
||||
bufferLine = line;
|
||||
}
|
||||
if (column != null && bufferColumn === -1) {
|
||||
bufferColumn = column;
|
||||
}
|
||||
buffer.push(str);
|
||||
|
||||
if (str == "\n") {
|
||||
var lineStr = "";
|
||||
for (var i = 0, len = buffer.length; i < len; i++) {
|
||||
lineStr += buffer[i];
|
||||
}
|
||||
result.add(new SourceNode(bufferLine, bufferColumn, options.url,
|
||||
lineStr));
|
||||
buffer.splice(0, buffer.length);
|
||||
bufferLine = -1;
|
||||
bufferColumn = -1;
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
||||
// Whether or not we added a newline on after we added the last token.
|
||||
var addedNewline = false;
|
||||
|
||||
// The current token we will be adding to the pretty printed code.
|
||||
var token;
|
||||
|
||||
// Shorthand for token.type.label, so we don't have to repeatedly access
|
||||
// properties.
|
||||
var ttl;
|
||||
|
||||
// Shorthand for token.type.keyword, so we don't have to repeatedly access
|
||||
// properties.
|
||||
var ttk;
|
||||
|
||||
// The last token we added to the pretty printed code.
|
||||
var lastToken;
|
||||
|
||||
// Stack of token types/keywords that can affect whether we want to add a
|
||||
// newline or a space. We can make that decision based on what token type is
|
||||
// on the top of the stack. For example, a comma in a parameter list should
|
||||
// be followed by a space, while a comma in an object literal should be
|
||||
// followed by a newline.
|
||||
//
|
||||
// Strings that go on the stack:
|
||||
//
|
||||
// - "{"
|
||||
// - "("
|
||||
// - "["
|
||||
// - "[\n"
|
||||
// - "do"
|
||||
// - "?"
|
||||
// - "switch"
|
||||
// - "case"
|
||||
// - "default"
|
||||
//
|
||||
// The difference between "[" and "[\n" is that "[\n" is used when we are
|
||||
// treating "[" and "]" tokens as line delimiters and should increment and
|
||||
// decrement the indent level when we find them.
|
||||
var stack = [];
|
||||
|
||||
// Pass through acorn's tokenizer and append tokens and comments into a
|
||||
// single queue to process. For example, the source file:
|
||||
//
|
||||
// foo
|
||||
// // a
|
||||
// // b
|
||||
// bar
|
||||
//
|
||||
// After this process, tokenQueue has the following token stream:
|
||||
//
|
||||
// [ foo, '// a', '// b', bar]
|
||||
var tokenQueue = [];
|
||||
|
||||
var tokens = acorn.tokenizer(input, {
|
||||
locations: true,
|
||||
sourceFile: options.url,
|
||||
onComment: function (block, text, start, end, startLoc, endLoc) {
|
||||
tokenQueue.push({
|
||||
type: {},
|
||||
comment: true,
|
||||
block: block,
|
||||
text: text,
|
||||
loc: { start: startLoc, end: endLoc }
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
for (;;) {
|
||||
token = tokens.getToken();
|
||||
tokenQueue.push(token);
|
||||
if (token.type.label == "eof") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < tokenQueue.length; i++) {
|
||||
token = tokenQueue[i];
|
||||
|
||||
if (token.comment) {
|
||||
var commentIndentLevel = indentLevel;
|
||||
if (lastToken && (lastToken.loc.end.line == token.loc.start.line)) {
|
||||
commentIndentLevel = 0;
|
||||
write(" ");
|
||||
}
|
||||
addComment(write, commentIndentLevel, options, token.block, token.text,
|
||||
token.loc.start.line, token.loc.start.column);
|
||||
addedNewline = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
ttk = token.type.keyword;
|
||||
ttl = token.type.label;
|
||||
|
||||
if (ttl == "eof") {
|
||||
if (!addedNewline) {
|
||||
write("\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
token.isArrayLiteral = isArrayLiteral(token, lastToken);
|
||||
|
||||
if (belongsOnStack(token)) {
|
||||
if (token.isArrayLiteral) {
|
||||
stack.push("[\n");
|
||||
} else {
|
||||
stack.push(ttl || ttk);
|
||||
}
|
||||
}
|
||||
|
||||
if (decrementsIndent(ttl, stack)) {
|
||||
indentLevel--;
|
||||
if (ttl == "}"
|
||||
&& stack.length > 1
|
||||
&& stack[stack.length - 2] == "switch") {
|
||||
indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
prependWhiteSpace(token, lastToken, addedNewline, write, options,
|
||||
indentLevel, stack);
|
||||
addToken(token, write);
|
||||
|
||||
// If the next token is going to be a comment starting on the same line,
|
||||
// then no need to add one here
|
||||
var nextToken = tokenQueue[i + 1];
|
||||
if (!nextToken || !nextToken.comment || token.loc.end.line != nextToken.loc.start.line) {
|
||||
addedNewline = appendNewline(token, write, stack);
|
||||
}
|
||||
|
||||
if (shouldStackPop(token, stack)) {
|
||||
stack.pop();
|
||||
if (token == "}" && stack.length
|
||||
&& stack[stack.length - 1] == "switch") {
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
if (incrementsIndent(token)) {
|
||||
indentLevel++;
|
||||
}
|
||||
|
||||
// Acorn's tokenizer re-uses tokens, so we have to copy the last token on
|
||||
// every iteration. We follow acorn's lead here, and reuse the lastToken
|
||||
// object the same way that acorn reuses the token object. This allows us
|
||||
// to avoid allocations and minimize GC pauses.
|
||||
if (!lastToken) {
|
||||
lastToken = { loc: { start: {}, end: {} } };
|
||||
}
|
||||
lastToken.start = token.start;
|
||||
lastToken.end = token.end;
|
||||
lastToken.loc.start.line = token.loc.start.line;
|
||||
lastToken.loc.start.column = token.loc.start.column;
|
||||
lastToken.loc.end.line = token.loc.end.line;
|
||||
lastToken.loc.end.column = token.loc.end.column;
|
||||
lastToken.type = token.type;
|
||||
lastToken.value = token.value;
|
||||
lastToken.isArrayLiteral = token.isArrayLiteral;
|
||||
}
|
||||
|
||||
return result.toStringWithSourceMap({ file: options.url });
|
||||
};
|
||||
|
||||
}.bind(this)));
|
||||
49
devtools/shared/pretty-fast/tests/unit/head_pretty-fast.js
Normal file
49
devtools/shared/pretty-fast/tests/unit/head_pretty-fast.js
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
"use strict";
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var Cu = Components.utils;
|
||||
var Cr = Components.results;
|
||||
|
||||
const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
|
||||
this.sourceMap = require("source-map");
|
||||
this.acorn = require("acorn/acorn");
|
||||
this.prettyFast = require("devtools/shared/pretty-fast/pretty-fast");
|
||||
const { console } = Cu.import("resource://gre/modules/Console.jsm", {});
|
||||
|
||||
// Register a console listener, so console messages don't just disappear
|
||||
// into the ether.
|
||||
var errorCount = 0;
|
||||
var listener = {
|
||||
observe: function (aMessage) {
|
||||
errorCount++;
|
||||
try {
|
||||
// If we've been given an nsIScriptError, then we can print out
|
||||
// something nicely formatted, for tools like Emacs to pick up.
|
||||
var scriptError = aMessage.QueryInterface(Ci.nsIScriptError);
|
||||
dump(aMessage.sourceName + ":" + aMessage.lineNumber + ": " +
|
||||
scriptErrorFlagsToKind(aMessage.flags) + ": " +
|
||||
aMessage.errorMessage + "\n");
|
||||
var string = aMessage.errorMessage;
|
||||
} catch (x) {
|
||||
// Be a little paranoid with message, as the whole goal here is to lose
|
||||
// no information.
|
||||
try {
|
||||
var string = "" + aMessage.message;
|
||||
} catch (x) {
|
||||
var string = "<error converting error message to string>";
|
||||
}
|
||||
}
|
||||
|
||||
// Ignored until they are fixed in bug 1242968.
|
||||
if (string.includes("JavaScript Warning")) {
|
||||
return;
|
||||
}
|
||||
|
||||
do_throw("head_pretty-fast.js got console message: " + string + "\n");
|
||||
}
|
||||
};
|
||||
|
||||
var consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
|
||||
consoleService.registerListener(listener);
|
||||
|
||||
572
devtools/shared/pretty-fast/tests/unit/test.js
Normal file
572
devtools/shared/pretty-fast/tests/unit/test.js
Normal file
|
|
@ -0,0 +1,572 @@
|
|||
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2; fill-column: 80 -*- */
|
||||
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
* Copyright 2013 Mozilla Foundation and contributors
|
||||
* Licensed under the New BSD license. See LICENSE.md or:
|
||||
* http://opensource.org/licenses/BSD-2-Clause
|
||||
*/
|
||||
var prettyFast = this.prettyFast || require("./pretty-fast");
|
||||
|
||||
var testCases = [
|
||||
|
||||
{
|
||||
name: "Simple function",
|
||||
input: "function foo() { bar(); }",
|
||||
output: "function foo() {\n" +
|
||||
" bar();\n" +
|
||||
"}\n",
|
||||
mappings: [
|
||||
// function foo() {
|
||||
{
|
||||
inputLine: 1,
|
||||
outputLine: 1
|
||||
},
|
||||
// bar();
|
||||
{
|
||||
inputLine: 1,
|
||||
outputLine: 2
|
||||
},
|
||||
// }
|
||||
{
|
||||
inputLine: 1,
|
||||
outputLine: 3
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
name: "Nested function",
|
||||
input: "function foo() { function bar() { debugger; } bar(); }",
|
||||
output: "function foo() {\n" +
|
||||
" function bar() {\n" +
|
||||
" debugger;\n" +
|
||||
" }\n" +
|
||||
" bar();\n" +
|
||||
"}\n",
|
||||
mappings: [
|
||||
// function bar() {
|
||||
{
|
||||
inputLine: 1,
|
||||
outputLine: 2
|
||||
},
|
||||
// debugger;
|
||||
{
|
||||
inputLine: 1,
|
||||
outputLine: 3
|
||||
},
|
||||
// bar();
|
||||
{
|
||||
inputLine: 1,
|
||||
outputLine: 5
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
name: "Immediately invoked function expression",
|
||||
input: "(function(){thingy()}())",
|
||||
output: "(function () {\n" +
|
||||
" thingy()\n" +
|
||||
"}())\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Single line comment",
|
||||
input: "// Comment\n" +
|
||||
"function foo() { bar(); }\n",
|
||||
output: "// Comment\n" +
|
||||
"function foo() {\n" +
|
||||
" bar();\n" +
|
||||
"}\n",
|
||||
mappings: [
|
||||
// // Comment
|
||||
{
|
||||
inputLine: 1,
|
||||
outputLine: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
name: "Multi line comment",
|
||||
input: "/* Comment\n" +
|
||||
"more comment */\n" +
|
||||
"function foo() { bar(); }\n",
|
||||
output: "/* Comment\n" +
|
||||
"more comment */\n" +
|
||||
"function foo() {\n" +
|
||||
" bar();\n" +
|
||||
"}\n",
|
||||
mappings: [
|
||||
// /* Comment
|
||||
{
|
||||
inputLine: 1,
|
||||
outputLine: 1
|
||||
},
|
||||
// \nmore comment */
|
||||
{
|
||||
inputLine: 1,
|
||||
outputLine: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
name: "Null assignment",
|
||||
input: "var i=null;\n",
|
||||
output: "var i = null;\n",
|
||||
mappings: [
|
||||
{
|
||||
inputLine: 1,
|
||||
outputLine: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
name: "Undefined assignment",
|
||||
input: "var i=undefined;\n",
|
||||
output: "var i = undefined;\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Void 0 assignment",
|
||||
input: "var i=void 0;\n",
|
||||
output: "var i = void 0;\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "This property access",
|
||||
input: "var foo=this.foo;\n",
|
||||
output: "var foo = this.foo;\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "True assignment",
|
||||
input: "var foo=true;\n",
|
||||
output: "var foo = true;\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "False assignment",
|
||||
input: "var foo=false;\n",
|
||||
output: "var foo = false;\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "For loop",
|
||||
input: "for (var i = 0; i < n; i++) { console.log(i); }",
|
||||
output: "for (var i = 0; i < n; i++) {\n" +
|
||||
" console.log(i);\n" +
|
||||
"}\n",
|
||||
mappings: [
|
||||
// for (var i = 0; i < n; i++) {
|
||||
{
|
||||
inputLine: 1,
|
||||
outputLine: 1
|
||||
},
|
||||
// console.log(i);
|
||||
{
|
||||
inputLine: 1,
|
||||
outputLine: 2
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
name: "String with semicolon",
|
||||
input: "var foo = ';';\n",
|
||||
output: "var foo = ';';\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "String with quote",
|
||||
input: "var foo = \"'\";\n",
|
||||
output: "var foo = '\\'';\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Function calls",
|
||||
input: "var result=func(a,b,c,d);",
|
||||
output: "var result = func(a, b, c, d);\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Regexp",
|
||||
input: "var r=/foobar/g;",
|
||||
output: "var r = /foobar/g;\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "In operator",
|
||||
input: "if(foo in bar){doThing()}",
|
||||
output: "if (foo in bar) {\n" +
|
||||
" doThing()\n" +
|
||||
"}\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "With statement",
|
||||
input: "with(obj){crock()}",
|
||||
output: "with (obj) {\n" +
|
||||
" crock()\n" +
|
||||
"}\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "New expression",
|
||||
input: "var foo=new Foo();",
|
||||
output: "var foo = new Foo();\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Continue/break statements",
|
||||
input: "while(1){if(x){continue}if(y){break}if(z){break foo}}",
|
||||
output: "while (1) {\n" +
|
||||
" if (x) {\n" +
|
||||
" continue\n" +
|
||||
" }\n" +
|
||||
" if (y) {\n" +
|
||||
" break\n" +
|
||||
" }\n" +
|
||||
" if (z) {\n" +
|
||||
" break foo\n" +
|
||||
" }\n" +
|
||||
"}\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Instanceof",
|
||||
input: "var a=x instanceof y;",
|
||||
output: "var a = x instanceof y;\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Binary operators",
|
||||
input: "var a=5*30;var b=5>>3;",
|
||||
output: "var a = 5 * 30;\n" +
|
||||
"var b = 5 >> 3;\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Delete",
|
||||
input: "delete obj.prop;",
|
||||
output: "delete obj.prop;\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Try/catch/finally statement",
|
||||
input: "try{dangerous()}catch(e){handle(e)}finally{cleanup()}",
|
||||
output: "try {\n" +
|
||||
" dangerous()\n" +
|
||||
"} catch (e) {\n" +
|
||||
" handle(e)\n" +
|
||||
"} finally {\n" +
|
||||
" cleanup()\n" +
|
||||
"}\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "If/else statement",
|
||||
input: "if(c){then()}else{other()}",
|
||||
output: "if (c) {\n" +
|
||||
" then()\n" +
|
||||
"} else {\n" +
|
||||
" other()\n" +
|
||||
"}\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "If/else without curlies",
|
||||
input: "if(c) a else b",
|
||||
output: "if (c) a else b\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Objects",
|
||||
input: "var o={a:1,\n" +
|
||||
" b:2};",
|
||||
output: "var o = {\n" +
|
||||
" a: 1,\n" +
|
||||
" b: 2\n" +
|
||||
"};\n",
|
||||
mappings: [
|
||||
// a: 1,
|
||||
{
|
||||
inputLine: 1,
|
||||
outputLine: 2
|
||||
},
|
||||
// b: 2
|
||||
{
|
||||
inputLine: 2,
|
||||
outputLine: 3
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
name: "Do/while loop",
|
||||
input: "do{x}while(y)",
|
||||
output: "do {\n" +
|
||||
" x\n" +
|
||||
"} while (y)\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Arrays",
|
||||
input: "var a=[1,2,3];",
|
||||
output: "var a = [\n" +
|
||||
" 1,\n" +
|
||||
" 2,\n" +
|
||||
" 3\n" +
|
||||
"];\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Code that relies on ASI",
|
||||
input: "var foo = 10\n" +
|
||||
"var bar = 20\n" +
|
||||
"function g() {\n" +
|
||||
" a()\n" +
|
||||
" b()\n" +
|
||||
"}",
|
||||
output: "var foo = 10\n" +
|
||||
"var bar = 20\n" +
|
||||
"function g() {\n" +
|
||||
" a()\n" +
|
||||
" b()\n" +
|
||||
"}\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Ternary operator",
|
||||
input: "bar?baz:bang;",
|
||||
output: "bar ? baz : bang;\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Switch statements",
|
||||
input: "switch(x){case a:foo();break;default:bar()}",
|
||||
output: "switch (x) {\n" +
|
||||
" case a:\n" +
|
||||
" foo();\n" +
|
||||
" break;\n" +
|
||||
" default:\n" +
|
||||
" bar()\n" +
|
||||
"}\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Multiple single line comments",
|
||||
input: "function f() {\n" +
|
||||
" // a\n" +
|
||||
" // b\n" +
|
||||
" // c\n" +
|
||||
"}\n",
|
||||
output: "function f() {\n" +
|
||||
" // a\n" +
|
||||
" // b\n" +
|
||||
" // c\n" +
|
||||
"}\n",
|
||||
},
|
||||
|
||||
{
|
||||
name: "Indented multiline comment",
|
||||
input: "function foo() {\n" +
|
||||
" /**\n" +
|
||||
" * java doc style comment\n" +
|
||||
" * more comment\n" +
|
||||
" */\n" +
|
||||
" bar();\n" +
|
||||
"}\n",
|
||||
output: "function foo() {\n" +
|
||||
" /**\n" +
|
||||
" * java doc style comment\n" +
|
||||
" * more comment\n" +
|
||||
" */\n" +
|
||||
" bar();\n" +
|
||||
"}\n",
|
||||
},
|
||||
|
||||
{
|
||||
name: "ASI return",
|
||||
input: "function f() {\n" +
|
||||
" return\n" +
|
||||
" {}\n" +
|
||||
"}\n",
|
||||
output: "function f() {\n" +
|
||||
" return\n" +
|
||||
" {\n" +
|
||||
" }\n" +
|
||||
"}\n",
|
||||
},
|
||||
|
||||
{
|
||||
name: "Non-ASI property access",
|
||||
input: "[1,2,3]\n" +
|
||||
"[0]",
|
||||
output: "[\n" +
|
||||
" 1,\n" +
|
||||
" 2,\n" +
|
||||
" 3\n" +
|
||||
"]\n" +
|
||||
"[0]\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Non-ASI in",
|
||||
input: "'x'\n" +
|
||||
"in foo",
|
||||
output: "'x' in foo\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Non-ASI function call",
|
||||
input: "f\n" +
|
||||
"()",
|
||||
output: "f()\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Non-ASI new",
|
||||
input: "new\n" +
|
||||
"F()",
|
||||
output: "new F()\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Getter and setter literals",
|
||||
input: "var obj={get foo(){return this._foo},set foo(v){this._foo=v}}",
|
||||
output: "var obj = {\n" +
|
||||
" get foo() {\n" +
|
||||
" return this._foo\n" +
|
||||
" },\n" +
|
||||
" set foo(v) {\n" +
|
||||
" this._foo = v\n" +
|
||||
" }\n" +
|
||||
"}\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Escaping backslashes in strings",
|
||||
input: "'\\\\'\n",
|
||||
output: "'\\\\'\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Escaping carriage return in strings",
|
||||
input: "'\\r'\n",
|
||||
output: "'\\r'\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Escaping tab in strings",
|
||||
input: "'\\t'\n",
|
||||
output: "'\\t'\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Escaping vertical tab in strings",
|
||||
input: "'\\v'\n",
|
||||
output: "'\\v'\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Escaping form feed in strings",
|
||||
input: "'\\f'\n",
|
||||
output: "'\\f'\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Escaping null character in strings",
|
||||
input: "'\\0'\n",
|
||||
output: "'\\0'\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Bug 977082 - space between grouping operator and dot notation",
|
||||
input: "JSON.stringify(3).length;\n" +
|
||||
"([1,2,3]).length;\n" +
|
||||
"(new Date()).toLocaleString();\n",
|
||||
output: "JSON.stringify(3).length;\n" +
|
||||
"([1,\n" +
|
||||
"2,\n" +
|
||||
"3]).length;\n" +
|
||||
"(new Date()).toLocaleString();\n"
|
||||
},
|
||||
|
||||
{
|
||||
name: "Bug 975477 don't move end of line comments to next line",
|
||||
input: "switch (request.action) {\n" +
|
||||
" case 'show': //$NON-NLS-0$\n" +
|
||||
" if (localStorage.hideicon !== 'true') { //$NON-NLS-0$\n" +
|
||||
" chrome.pageAction.show(sender.tab.id);\n" +
|
||||
" }\n" +
|
||||
" break;\n" +
|
||||
" case 'hide': /*Multiline\n" +
|
||||
" Comment */" +
|
||||
" break;\n" +
|
||||
" default:\n" +
|
||||
" console.warn('unknown request'); //$NON-NLS-0$\n" +
|
||||
" // don't respond if you don't understand the message.\n" +
|
||||
" return;\n" +
|
||||
"}\n",
|
||||
output: "switch (request.action) {\n" +
|
||||
" case 'show': //$NON-NLS-0$\n" +
|
||||
" if (localStorage.hideicon !== 'true') { //$NON-NLS-0$\n" +
|
||||
" chrome.pageAction.show(sender.tab.id);\n" +
|
||||
" }\n" +
|
||||
" break;\n" +
|
||||
" case 'hide': /*Multiline\n" +
|
||||
" Comment */\n" +
|
||||
" break;\n" +
|
||||
" default:\n" +
|
||||
" console.warn('unknown request'); //$NON-NLS-0$\n" +
|
||||
" // don't respond if you don't understand the message.\n" +
|
||||
" return;\n" +
|
||||
"}\n"
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
var sourceMap = this.sourceMap || require("source-map");
|
||||
|
||||
function run_test() {
|
||||
testCases.forEach(function (test) {
|
||||
console.log(test.name);
|
||||
|
||||
var actual = prettyFast(test.input, {
|
||||
indent: " ",
|
||||
url: "test.js"
|
||||
});
|
||||
|
||||
if (actual.code !== test.output) {
|
||||
throw new Error("Expected:\n" + test.output
|
||||
+ "\nGot:\n" + actual.code);
|
||||
}
|
||||
|
||||
if (test.mappings) {
|
||||
var smc = new sourceMap.SourceMapConsumer(actual.map.toJSON());
|
||||
test.mappings.forEach(function (m) {
|
||||
var query = { line: m.outputLine, column: 0 };
|
||||
var original = smc.originalPositionFor(query);
|
||||
if (original.line != m.inputLine) {
|
||||
throw new Error("Querying:\n" + JSON.stringify(query, null, 2) + "\n"
|
||||
+ "Expected line:\n" + m.inputLine + "\n"
|
||||
+ "Got:\n" + JSON.stringify(original, null, 2));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
console.log("✓ All tests pass!");
|
||||
}
|
||||
|
||||
// Only run the tests if this is node and we are running this file
|
||||
// directly. (Firefox's test runner will import this test file, and then call
|
||||
// run_test itself.)
|
||||
if (typeof require == "function" && typeof module == "object"
|
||||
&& require.main === module) {
|
||||
run_test();
|
||||
}
|
||||
8
devtools/shared/pretty-fast/tests/unit/xpcshell.ini
Normal file
8
devtools/shared/pretty-fast/tests/unit/xpcshell.ini
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
[DEFAULT]
|
||||
tags = devtools
|
||||
head = head_pretty-fast.js
|
||||
tail =
|
||||
firefox-appdir = browser
|
||||
skip-if = toolkit == 'android'
|
||||
|
||||
[test.js]
|
||||
Loading…
Add table
Add a link
Reference in a new issue