mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 16:41:07 +00:00
Run dartfmt on js_ast
BUG= R=sra@google.com Review-Url: https://codereview.chromium.org/2748103010 .
This commit is contained in:
parent
33717e010a
commit
11950984e4
|
@ -7,7 +7,6 @@
|
|||
|
||||
part of js_ast;
|
||||
|
||||
|
||||
/**
|
||||
* Global template manager. We should aim to have a fixed number of
|
||||
* templates. This implies that we do not use js('xxx') to parse text that is
|
||||
|
@ -18,7 +17,6 @@ part of js_ast;
|
|||
*/
|
||||
TemplateManager templateManager = new TemplateManager();
|
||||
|
||||
|
||||
/**
|
||||
|
||||
[js] is a singleton instace of JsBuilder. JsBuilder is a set of conveniences
|
||||
|
@ -187,7 +185,6 @@ What is not implemented:
|
|||
*/
|
||||
const JsBuilder js = const JsBuilder();
|
||||
|
||||
|
||||
class JsBuilder {
|
||||
const JsBuilder();
|
||||
|
||||
|
@ -271,8 +268,8 @@ class JsBuilder {
|
|||
Template uncachedExpressionTemplate(String source) {
|
||||
MiniJsParser parser = new MiniJsParser(source);
|
||||
Expression expression = parser.expression();
|
||||
return new Template(
|
||||
source, expression, isExpression: true, forceCopy: false);
|
||||
return new Template(source, expression,
|
||||
isExpression: true, forceCopy: false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -281,8 +278,8 @@ class JsBuilder {
|
|||
Template uncachedStatementTemplate(String source) {
|
||||
MiniJsParser parser = new MiniJsParser(source);
|
||||
Statement statement = parser.statement();
|
||||
return new Template(
|
||||
source, statement, isExpression: false, forceCopy: false);
|
||||
return new Template(source, statement,
|
||||
isExpression: false, forceCopy: false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -300,19 +297,26 @@ class JsBuilder {
|
|||
|
||||
/// Creates a literal js string from [value].
|
||||
LiteralString _legacyEscapedString(String value) {
|
||||
// Start by escaping the backslashes.
|
||||
// Start by escaping the backslashes.
|
||||
String escaped = value.replaceAll('\\', '\\\\');
|
||||
// Do not escape unicode characters and ' because they are allowed in the
|
||||
// string literal anyway.
|
||||
escaped = escaped.replaceAllMapped(new RegExp('\n|"|\b|\t|\v|\r'), (match) {
|
||||
switch (match.group(0)) {
|
||||
case "\n" : return r"\n";
|
||||
case "\"" : return r'\"';
|
||||
case "\b" : return r"\b";
|
||||
case "\t" : return r"\t";
|
||||
case "\f" : return r"\f";
|
||||
case "\r" : return r"\r";
|
||||
case "\v" : return r"\v";
|
||||
case "\n":
|
||||
return r"\n";
|
||||
case "\"":
|
||||
return r'\"';
|
||||
case "\b":
|
||||
return r"\b";
|
||||
case "\t":
|
||||
return r"\t";
|
||||
case "\f":
|
||||
return r"\f";
|
||||
case "\r":
|
||||
return r"\r";
|
||||
case "\v":
|
||||
return r"\v";
|
||||
}
|
||||
});
|
||||
LiteralString result = string(escaped);
|
||||
|
@ -324,7 +328,7 @@ class JsBuilder {
|
|||
|
||||
/// Creates a literal js string from [value].
|
||||
LiteralString escapedString(String value,
|
||||
{bool utf8: false, bool ascii: false}) {
|
||||
{bool utf8: false, bool ascii: false}) {
|
||||
if (utf8 == false && ascii == false) return _legacyEscapedString(value);
|
||||
if (utf8 && ascii) throw new ArgumentError('Cannot be both UTF8 and ASCII');
|
||||
|
||||
|
@ -340,12 +344,16 @@ class JsBuilder {
|
|||
++singleQuotes;
|
||||
} else if (rune == charCodes.$DQ) {
|
||||
++doubleQuotes;
|
||||
} else if (rune == charCodes.$LF || rune == charCodes.$CR ||
|
||||
rune == charCodes.$LS || rune == charCodes.$PS) {
|
||||
} else if (rune == charCodes.$LF ||
|
||||
rune == charCodes.$CR ||
|
||||
rune == charCodes.$LS ||
|
||||
rune == charCodes.$PS) {
|
||||
// Line terminators.
|
||||
++otherEscapes;
|
||||
} else if (rune == charCodes.$BS || rune == charCodes.$TAB ||
|
||||
rune == charCodes.$VTAB || rune == charCodes.$FF) {
|
||||
} else if (rune == charCodes.$BS ||
|
||||
rune == charCodes.$TAB ||
|
||||
rune == charCodes.$VTAB ||
|
||||
rune == charCodes.$FF) {
|
||||
++otherEscapes;
|
||||
} else if (_isUnpairedSurrogate(rune)) {
|
||||
++unpairedSurrogates;
|
||||
|
@ -408,15 +416,24 @@ class JsBuilder {
|
|||
|
||||
static String _irregularEscape(int code, bool useSingleQuotes) {
|
||||
switch (code) {
|
||||
case charCodes.$SQ: return useSingleQuotes ? r"\'" : r"'";
|
||||
case charCodes.$DQ: return useSingleQuotes ? r'"' : r'\"';
|
||||
case charCodes.$BACKSLASH: return r'\\';
|
||||
case charCodes.$BS: return r'\b';
|
||||
case charCodes.$TAB: return r'\t';
|
||||
case charCodes.$LF: return r'\n';
|
||||
case charCodes.$VTAB: return r'\v';
|
||||
case charCodes.$FF: return r'\f';
|
||||
case charCodes.$CR: return r'\r';
|
||||
case charCodes.$SQ:
|
||||
return useSingleQuotes ? r"\'" : r"'";
|
||||
case charCodes.$DQ:
|
||||
return useSingleQuotes ? r'"' : r'\"';
|
||||
case charCodes.$BACKSLASH:
|
||||
return r'\\';
|
||||
case charCodes.$BS:
|
||||
return r'\b';
|
||||
case charCodes.$TAB:
|
||||
return r'\t';
|
||||
case charCodes.$LF:
|
||||
return r'\n';
|
||||
case charCodes.$VTAB:
|
||||
return r'\v';
|
||||
case charCodes.$FF:
|
||||
return r'\f';
|
||||
case charCodes.$CR:
|
||||
return r'\r';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -435,13 +452,13 @@ class JsBuilder {
|
|||
LiteralString stringPart(String value) => new LiteralString(value);
|
||||
|
||||
StringConcatenation concatenateStrings(Iterable<Literal> parts,
|
||||
{addQuotes: false}) {
|
||||
{addQuotes: false}) {
|
||||
List<Literal> _parts;
|
||||
if (addQuotes) {
|
||||
Literal quote = stringPart('"');
|
||||
_parts = <Literal>[quote]
|
||||
..addAll(parts)
|
||||
..add(quote);
|
||||
..addAll(parts)
|
||||
..add(quote);
|
||||
} else {
|
||||
_parts = new List.from(parts, growable: false);
|
||||
}
|
||||
|
@ -472,9 +489,8 @@ class JsBuilder {
|
|||
|
||||
Comment comment(String text) => new Comment(text);
|
||||
|
||||
Call propertyCall(Expression receiver,
|
||||
Expression fieldName,
|
||||
List<Expression> arguments) {
|
||||
Call propertyCall(
|
||||
Expression receiver, Expression fieldName, List<Expression> arguments) {
|
||||
return new Call(new PropertyAccess(receiver, fieldName), arguments);
|
||||
}
|
||||
|
||||
|
@ -491,29 +507,31 @@ LiteralString string(String value) => js.string(value);
|
|||
LiteralString quoteName(Name name, {allowNull: false}) {
|
||||
return js.quoteName(name, allowNull: allowNull);
|
||||
}
|
||||
|
||||
LiteralString stringPart(String value) => js.stringPart(value);
|
||||
Iterable<Literal> joinLiterals(Iterable<Literal> list, Literal separator) {
|
||||
return js.joinLiterals(list, separator);
|
||||
}
|
||||
|
||||
StringConcatenation concatenateStrings(Iterable<Literal> parts,
|
||||
{addQuotes: false}) {
|
||||
{addQuotes: false}) {
|
||||
return js.concatenateStrings(parts, addQuotes: addQuotes);
|
||||
}
|
||||
|
||||
LiteralNumber number(num value) => js.number(value);
|
||||
ArrayInitializer numArray(Iterable<int> list) => js.numArray(list);
|
||||
ArrayInitializer stringArray(Iterable<String> list) => js.stringArray(list);
|
||||
Call propertyCall(Expression receiver,
|
||||
Expression fieldName,
|
||||
List<Expression> arguments) {
|
||||
Call propertyCall(
|
||||
Expression receiver, Expression fieldName, List<Expression> arguments) {
|
||||
return js.propertyCall(receiver, fieldName, arguments);
|
||||
}
|
||||
|
||||
ObjectInitializer objectLiteral(Map<String, Expression> map) {
|
||||
return js.objectLiteral(map);
|
||||
}
|
||||
|
||||
class MiniJsParserError {
|
||||
MiniJsParserError(this.parser, this.message) { }
|
||||
MiniJsParserError(this.parser, this.message) {}
|
||||
|
||||
final MiniJsParser parser;
|
||||
final String message;
|
||||
|
@ -575,7 +593,7 @@ class MiniJsParser {
|
|||
String lastToken = null;
|
||||
int lastPosition = 0;
|
||||
int position = 0;
|
||||
bool skippedNewline = false; // skipped newline in last getToken?
|
||||
bool skippedNewline = false; // skipped newline in last getToken?
|
||||
final String src;
|
||||
|
||||
final List<InterpolatedNode> interpolatedValues = <InterpolatedNode>[];
|
||||
|
@ -610,49 +628,70 @@ class MiniJsParser {
|
|||
|
||||
static String categoryToString(int cat) {
|
||||
switch (cat) {
|
||||
case NONE: return "NONE";
|
||||
case ALPHA: return "ALPHA";
|
||||
case NUMERIC: return "NUMERIC";
|
||||
case SYMBOL: return "SYMBOL";
|
||||
case ASSIGNMENT: return "ASSIGNMENT";
|
||||
case DOT: return "DOT";
|
||||
case LPAREN: return "LPAREN";
|
||||
case RPAREN: return "RPAREN";
|
||||
case LBRACE: return "LBRACE";
|
||||
case RBRACE: return "RBRACE";
|
||||
case LSQUARE: return "LSQUARE";
|
||||
case RSQUARE: return "RSQUARE";
|
||||
case STRING: return "STRING";
|
||||
case COMMA: return "COMMA";
|
||||
case QUERY: return "QUERY";
|
||||
case COLON: return "COLON";
|
||||
case SEMICOLON: return "SEMICOLON";
|
||||
case HASH: return "HASH";
|
||||
case WHITESPACE: return "WHITESPACE";
|
||||
case OTHER: return "OTHER";
|
||||
case NONE:
|
||||
return "NONE";
|
||||
case ALPHA:
|
||||
return "ALPHA";
|
||||
case NUMERIC:
|
||||
return "NUMERIC";
|
||||
case SYMBOL:
|
||||
return "SYMBOL";
|
||||
case ASSIGNMENT:
|
||||
return "ASSIGNMENT";
|
||||
case DOT:
|
||||
return "DOT";
|
||||
case LPAREN:
|
||||
return "LPAREN";
|
||||
case RPAREN:
|
||||
return "RPAREN";
|
||||
case LBRACE:
|
||||
return "LBRACE";
|
||||
case RBRACE:
|
||||
return "RBRACE";
|
||||
case LSQUARE:
|
||||
return "LSQUARE";
|
||||
case RSQUARE:
|
||||
return "RSQUARE";
|
||||
case STRING:
|
||||
return "STRING";
|
||||
case COMMA:
|
||||
return "COMMA";
|
||||
case QUERY:
|
||||
return "QUERY";
|
||||
case COLON:
|
||||
return "COLON";
|
||||
case SEMICOLON:
|
||||
return "SEMICOLON";
|
||||
case HASH:
|
||||
return "HASH";
|
||||
case WHITESPACE:
|
||||
return "WHITESPACE";
|
||||
case OTHER:
|
||||
return "OTHER";
|
||||
}
|
||||
return "Unknown: $cat";
|
||||
}
|
||||
|
||||
static const CATEGORIES = const <int>[
|
||||
OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 0-7
|
||||
OTHER, WHITESPACE, WHITESPACE, OTHER, OTHER, WHITESPACE, // 8-13
|
||||
OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 14-21
|
||||
OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 22-29
|
||||
OTHER, OTHER, WHITESPACE, // 30-32
|
||||
SYMBOL, OTHER, HASH, ALPHA, SYMBOL, SYMBOL, OTHER, // !"#$%&´
|
||||
LPAREN, RPAREN, SYMBOL, SYMBOL, COMMA, SYMBOL, DOT, SYMBOL, // ()*+,-./
|
||||
NUMERIC, NUMERIC, NUMERIC, NUMERIC, NUMERIC, // 01234
|
||||
NUMERIC, NUMERIC, NUMERIC, NUMERIC, NUMERIC, // 56789
|
||||
COLON, SEMICOLON, SYMBOL, SYMBOL, SYMBOL, QUERY, OTHER, // :;<=>?@
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // ABCDEFGH
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // IJKLMNOP
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // QRSTUVWX
|
||||
ALPHA, ALPHA, LSQUARE, OTHER, RSQUARE, SYMBOL, ALPHA, OTHER, // YZ[\]^_'
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // abcdefgh
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // ijklmnop
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // qrstuvwx
|
||||
ALPHA, ALPHA, LBRACE, SYMBOL, RBRACE, SYMBOL]; // yz{|}~
|
||||
OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 0-7
|
||||
OTHER, WHITESPACE, WHITESPACE, OTHER, OTHER, WHITESPACE, // 8-13
|
||||
OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 14-21
|
||||
OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, // 22-29
|
||||
OTHER, OTHER, WHITESPACE, // 30-32
|
||||
SYMBOL, OTHER, HASH, ALPHA, SYMBOL, SYMBOL, OTHER, // !"#$%&´
|
||||
LPAREN, RPAREN, SYMBOL, SYMBOL, COMMA, SYMBOL, DOT, SYMBOL, // ()*+,-./
|
||||
NUMERIC, NUMERIC, NUMERIC, NUMERIC, NUMERIC, // 01234
|
||||
NUMERIC, NUMERIC, NUMERIC, NUMERIC, NUMERIC, // 56789
|
||||
COLON, SEMICOLON, SYMBOL, SYMBOL, SYMBOL, QUERY, OTHER, // :;<=>?@
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // ABCDEFGH
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // IJKLMNOP
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // QRSTUVWX
|
||||
ALPHA, ALPHA, LSQUARE, OTHER, RSQUARE, SYMBOL, ALPHA, OTHER, // YZ[\]^_'
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // abcdefgh
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // ijklmnop
|
||||
ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, // qrstuvwx
|
||||
ALPHA, ALPHA, LBRACE, SYMBOL, RBRACE, SYMBOL
|
||||
]; // yz{|}~
|
||||
|
||||
// This must be a >= the highest precedence number handled by parseBinary.
|
||||
static var HIGHEST_PARSE_BINARY_PRECEDENCE = 16;
|
||||
|
@ -660,22 +699,54 @@ class MiniJsParser {
|
|||
|
||||
// From https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Operator_Precedence
|
||||
static final BINARY_PRECEDENCE = {
|
||||
'+=': 17, '-=': 17, '*=': 17, '/=': 17, '%=': 17, '^=': 17, '|=': 17,
|
||||
'&=': 17, '<<=': 17, '>>=': 17, '>>>=': 17, '=': 17,
|
||||
'||': 14,
|
||||
'&&': 13,
|
||||
'|': 12,
|
||||
'^': 11,
|
||||
'&': 10,
|
||||
'!=': 9, '==': 9, '!==': 9, '===': 9,
|
||||
'<': 8, '<=': 8, '>=': 8, '>': 8, 'in': 8, 'instanceof': 8,
|
||||
'<<': 7, '>>': 7, '>>>': 7,
|
||||
'+': 6, '-': 6,
|
||||
'*': 5, '/': 5, '%': 5
|
||||
'+=': 17,
|
||||
'-=': 17,
|
||||
'*=': 17,
|
||||
'/=': 17,
|
||||
'%=': 17,
|
||||
'^=': 17,
|
||||
'|=': 17,
|
||||
'&=': 17,
|
||||
'<<=': 17,
|
||||
'>>=': 17,
|
||||
'>>>=': 17,
|
||||
'=': 17,
|
||||
'||': 14,
|
||||
'&&': 13,
|
||||
'|': 12,
|
||||
'^': 11,
|
||||
'&': 10,
|
||||
'!=': 9,
|
||||
'==': 9,
|
||||
'!==': 9,
|
||||
'===': 9,
|
||||
'<': 8,
|
||||
'<=': 8,
|
||||
'>=': 8,
|
||||
'>': 8,
|
||||
'in': 8,
|
||||
'instanceof': 8,
|
||||
'<<': 7,
|
||||
'>>': 7,
|
||||
'>>>': 7,
|
||||
'+': 6,
|
||||
'-': 6,
|
||||
'*': 5,
|
||||
'/': 5,
|
||||
'%': 5
|
||||
};
|
||||
static final UNARY_OPERATORS =
|
||||
['++', '--', '+', '-', '~', '!', 'typeof', 'void', 'delete', 'await']
|
||||
.toSet();
|
||||
static final UNARY_OPERATORS = [
|
||||
'++',
|
||||
'--',
|
||||
'+',
|
||||
'-',
|
||||
'~',
|
||||
'!',
|
||||
'typeof',
|
||||
'void',
|
||||
'delete',
|
||||
'await'
|
||||
].toSet();
|
||||
|
||||
static final OPERATORS_THAT_LOOK_LIKE_IDENTIFIERS =
|
||||
['typeof', 'void', 'delete', 'in', 'instanceof', 'await'].toSet();
|
||||
|
@ -697,8 +768,10 @@ class MiniJsParser {
|
|||
if (currentCode == charCodes.$BACKSLASH) {
|
||||
if (++position >= src.length) error("Unterminated literal");
|
||||
int escaped = src.codeUnitAt(position);
|
||||
if (escaped == charCodes.$x || escaped == charCodes.$X ||
|
||||
escaped == charCodes.$u || escaped == charCodes.$U ||
|
||||
if (escaped == charCodes.$x ||
|
||||
escaped == charCodes.$X ||
|
||||
escaped == charCodes.$u ||
|
||||
escaped == charCodes.$U ||
|
||||
category(escaped) == NUMERIC) {
|
||||
error('Numeric and hex escapes are not allowed in literals');
|
||||
}
|
||||
|
@ -714,8 +787,7 @@ class MiniJsParser {
|
|||
if (position >= src.length) break;
|
||||
int code = src.codeUnitAt(position);
|
||||
// Skip '//' and '/*' style comments.
|
||||
if (code == charCodes.$SLASH &&
|
||||
position + 1 < src.length) {
|
||||
if (code == charCodes.$SLASH && position + 1 < src.length) {
|
||||
if (src.codeUnitAt(position + 1) == charCodes.$SLASH) {
|
||||
int nextPosition = src.indexOf('\n', position);
|
||||
if (nextPosition == -1) nextPosition = src.length;
|
||||
|
@ -746,8 +818,8 @@ class MiniJsParser {
|
|||
lastCategory = STRING;
|
||||
lastToken = getDelimited(position);
|
||||
} else if (code == charCodes.$0 &&
|
||||
position + 2 < src.length &&
|
||||
src.codeUnitAt(position + 1) == charCodes.$x) {
|
||||
position + 2 < src.length &&
|
||||
src.codeUnitAt(position + 1) == charCodes.$x) {
|
||||
// Hex literal.
|
||||
for (position += 2; position < src.length; position++) {
|
||||
int cat = category(src.codeUnitAt(position));
|
||||
|
@ -777,16 +849,15 @@ class MiniJsParser {
|
|||
// Special code to disallow !, ~ and / in non-first position in token,
|
||||
// so that !! and ~~ parse as two tokens and != parses as one, while =/
|
||||
// parses as a an equals token followed by a regexp literal start.
|
||||
newCat =
|
||||
(code == charCodes.$BANG ||
|
||||
code == charCodes.$SLASH ||
|
||||
code == charCodes.$TILDE)
|
||||
newCat = (code == charCodes.$BANG ||
|
||||
code == charCodes.$SLASH ||
|
||||
code == charCodes.$TILDE)
|
||||
? NONE
|
||||
: category(code);
|
||||
} while (!singleCharCategory(cat) &&
|
||||
(cat == newCat ||
|
||||
(cat == ALPHA && newCat == NUMERIC) || // eg. level42.
|
||||
(cat == NUMERIC && newCat == DOT))); // eg. 3.1415
|
||||
(cat == newCat ||
|
||||
(cat == ALPHA && newCat == NUMERIC) || // eg. level42.
|
||||
(cat == NUMERIC && newCat == DOT))); // eg. 3.1415
|
||||
lastCategory = cat;
|
||||
lastToken = src.substring(lastPosition, position);
|
||||
if (cat == NUMERIC) {
|
||||
|
@ -829,7 +900,7 @@ class MiniJsParser {
|
|||
// Accept semicolon or automatically inserted semicolon before close brace.
|
||||
// Miniparser forbids other kinds of semicolon insertion.
|
||||
if (RBRACE == lastCategory) return true;
|
||||
if (NONE == lastCategory) return true; // end of input
|
||||
if (NONE == lastCategory) return true; // end of input
|
||||
if (skippedNewline) {
|
||||
error('No automatic semicolon insertion at preceding newline');
|
||||
}
|
||||
|
@ -984,7 +1055,8 @@ class MiniJsParser {
|
|||
propertyName = new LiteralString('"$identifier"');
|
||||
} else if (acceptCategory(STRING)) {
|
||||
propertyName = new LiteralString(identifier);
|
||||
} else if (acceptCategory(SYMBOL)) { // e.g. void
|
||||
} else if (acceptCategory(SYMBOL)) {
|
||||
// e.g. void
|
||||
propertyName = new LiteralString('"$identifier"');
|
||||
} else if (acceptCategory(HASH)) {
|
||||
var nameOrPosition = parseHash();
|
||||
|
@ -1034,9 +1106,9 @@ class MiniJsParser {
|
|||
expectCategory(COMMA);
|
||||
}
|
||||
}
|
||||
receiver = constructor ?
|
||||
new New(receiver, arguments) :
|
||||
new Call(receiver, arguments);
|
||||
receiver = constructor
|
||||
? new New(receiver, arguments)
|
||||
: new Call(receiver, arguments);
|
||||
constructor = false;
|
||||
} else if (!constructor && acceptCategory(LSQUARE)) {
|
||||
Expression inBraces = parseExpression();
|
||||
|
@ -1091,7 +1163,8 @@ class MiniJsParser {
|
|||
|
||||
Expression parseUnaryHigh() {
|
||||
String operator = lastToken;
|
||||
if (lastCategory == SYMBOL && UNARY_OPERATORS.contains(operator) &&
|
||||
if (lastCategory == SYMBOL &&
|
||||
UNARY_OPERATORS.contains(operator) &&
|
||||
(acceptString("++") || acceptString("--") || acceptString('await'))) {
|
||||
if (operator == "await") return new Await(parsePostfix());
|
||||
return new Prefix(operator, parsePostfix());
|
||||
|
@ -1101,8 +1174,10 @@ class MiniJsParser {
|
|||
|
||||
Expression parseUnaryLow() {
|
||||
String operator = lastToken;
|
||||
if (lastCategory == SYMBOL && UNARY_OPERATORS.contains(operator) &&
|
||||
operator != "++" && operator != "--") {
|
||||
if (lastCategory == SYMBOL &&
|
||||
UNARY_OPERATORS.contains(operator) &&
|
||||
operator != "++" &&
|
||||
operator != "--") {
|
||||
expectCategory(SYMBOL);
|
||||
if (operator == "await") return new Await(parsePostfix());
|
||||
return new Prefix(operator, parseUnaryLow());
|
||||
|
@ -1114,7 +1189,7 @@ class MiniJsParser {
|
|||
Expression lhs = parseUnaryLow();
|
||||
int minPrecedence;
|
||||
String lastSymbol;
|
||||
Expression rhs; // This is null first time around.
|
||||
Expression rhs; // This is null first time around.
|
||||
while (true) {
|
||||
String symbol = lastToken;
|
||||
if (lastCategory != SYMBOL ||
|
||||
|
@ -1146,7 +1221,6 @@ class MiniJsParser {
|
|||
return new Conditional(lhs, ifTrue, ifFalse);
|
||||
}
|
||||
|
||||
|
||||
Expression parseAssignment() {
|
||||
Expression lhs = parseConditional();
|
||||
String assignmentOperator = lastToken;
|
||||
|
@ -1154,7 +1228,7 @@ class MiniJsParser {
|
|||
Expression rhs = parseAssignment();
|
||||
if (assignmentOperator == "=") {
|
||||
return new Assignment(lhs, rhs);
|
||||
} else {
|
||||
} else {
|
||||
// Handle +=, -=, etc.
|
||||
String operator =
|
||||
assignmentOperator.substring(0, assignmentOperator.length - 1);
|
||||
|
@ -1280,7 +1354,6 @@ class MiniJsParser {
|
|||
if (lastToken == 'with') {
|
||||
error('Not implemented in mini parser');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool checkForInterpolatedStatement = lastCategory == HASH;
|
||||
|
@ -1387,8 +1460,8 @@ class MiniJsParser {
|
|||
expectCategory(RPAREN);
|
||||
Statement body = parseStatement();
|
||||
return new ForIn(
|
||||
new VariableDeclarationList([
|
||||
new VariableInitialization(declaration, null)]),
|
||||
new VariableDeclarationList(
|
||||
[new VariableInitialization(declaration, null)]),
|
||||
objectExpression,
|
||||
body);
|
||||
}
|
||||
|
@ -1450,8 +1523,8 @@ class MiniJsParser {
|
|||
}
|
||||
List statements = new List<Statement>();
|
||||
while (lastCategory != RBRACE &&
|
||||
lastToken != 'case' &&
|
||||
lastToken != 'default') {
|
||||
lastToken != 'case' &&
|
||||
lastToken != 'default') {
|
||||
statements.add(parseStatement());
|
||||
}
|
||||
return expression == null
|
||||
|
@ -1484,7 +1557,7 @@ class MiniJsParser {
|
|||
expectCategory(RPAREN);
|
||||
expectCategory(LBRACE);
|
||||
List<SwitchClause> clauses = new List<SwitchClause>();
|
||||
while(lastCategory != RBRACE) {
|
||||
while (lastCategory != RBRACE) {
|
||||
clauses.add(parseSwitchClause());
|
||||
}
|
||||
expectCategory(RBRACE);
|
||||
|
|
|
@ -6,7 +6,7 @@ library js_character_codes;
|
|||
|
||||
const int $EOF = 0;
|
||||
const int $STX = 2;
|
||||
const int $BS = 8;
|
||||
const int $BS = 8;
|
||||
const int $TAB = 9;
|
||||
const int $LF = 10;
|
||||
const int $VTAB = 11;
|
||||
|
|
|
@ -95,8 +95,7 @@ class BaseVisitor<T> implements NodeVisitor<T> {
|
|||
T visitJump(Statement node) => visitStatement(node);
|
||||
|
||||
T visitBlock(Block node) => visitStatement(node);
|
||||
T visitExpressionStatement(ExpressionStatement node)
|
||||
=> visitStatement(node);
|
||||
T visitExpressionStatement(ExpressionStatement node) => visitStatement(node);
|
||||
T visitEmptyStatement(EmptyStatement node) => visitStatement(node);
|
||||
T visitIf(If node) => visitStatement(node);
|
||||
T visitFor(For node) => visitLoop(node);
|
||||
|
@ -109,8 +108,7 @@ class BaseVisitor<T> implements NodeVisitor<T> {
|
|||
T visitThrow(Throw node) => visitJump(node);
|
||||
T visitTry(Try node) => visitStatement(node);
|
||||
T visitSwitch(Switch node) => visitStatement(node);
|
||||
T visitFunctionDeclaration(FunctionDeclaration node)
|
||||
=> visitStatement(node);
|
||||
T visitFunctionDeclaration(FunctionDeclaration node) => visitStatement(node);
|
||||
T visitLabeledStatement(LabeledStatement node) => visitStatement(node);
|
||||
T visitLiteralStatement(LiteralStatement node) => visitStatement(node);
|
||||
|
||||
|
@ -122,8 +120,8 @@ class BaseVisitor<T> implements NodeVisitor<T> {
|
|||
T visitVariableReference(VariableReference node) => visitExpression(node);
|
||||
|
||||
T visitLiteralExpression(LiteralExpression node) => visitExpression(node);
|
||||
T visitVariableDeclarationList(VariableDeclarationList node)
|
||||
=> visitExpression(node);
|
||||
T visitVariableDeclarationList(VariableDeclarationList node) =>
|
||||
visitExpression(node);
|
||||
T visitAssignment(Assignment node) => visitExpression(node);
|
||||
T visitVariableInitialization(VariableInitialization node) {
|
||||
if (node.value != null) {
|
||||
|
@ -132,6 +130,7 @@ class BaseVisitor<T> implements NodeVisitor<T> {
|
|||
return visitExpression(node);
|
||||
}
|
||||
}
|
||||
|
||||
T visitConditional(Conditional node) => visitExpression(node);
|
||||
T visitNew(New node) => visitExpression(node);
|
||||
T visitCall(Call node) => visitExpression(node);
|
||||
|
@ -141,8 +140,8 @@ class BaseVisitor<T> implements NodeVisitor<T> {
|
|||
T visitAccess(PropertyAccess node) => visitExpression(node);
|
||||
|
||||
T visitVariableUse(VariableUse node) => visitVariableReference(node);
|
||||
T visitVariableDeclaration(VariableDeclaration node)
|
||||
=> visitVariableReference(node);
|
||||
T visitVariableDeclaration(VariableDeclaration node) =>
|
||||
visitVariableReference(node);
|
||||
T visitParameter(Parameter node) => visitVariableDeclaration(node);
|
||||
T visitThis(This node) => visitParameter(node);
|
||||
|
||||
|
@ -174,16 +173,16 @@ class BaseVisitor<T> implements NodeVisitor<T> {
|
|||
|
||||
T visitInterpolatedNode(InterpolatedNode node) => visitNode(node);
|
||||
|
||||
T visitInterpolatedExpression(InterpolatedExpression node)
|
||||
=> visitInterpolatedNode(node);
|
||||
T visitInterpolatedLiteral(InterpolatedLiteral node)
|
||||
=> visitInterpolatedNode(node);
|
||||
T visitInterpolatedParameter(InterpolatedParameter node)
|
||||
=> visitInterpolatedNode(node);
|
||||
T visitInterpolatedSelector(InterpolatedSelector node)
|
||||
=> visitInterpolatedNode(node);
|
||||
T visitInterpolatedStatement(InterpolatedStatement node)
|
||||
=> visitInterpolatedNode(node);
|
||||
T visitInterpolatedExpression(InterpolatedExpression node) =>
|
||||
visitInterpolatedNode(node);
|
||||
T visitInterpolatedLiteral(InterpolatedLiteral node) =>
|
||||
visitInterpolatedNode(node);
|
||||
T visitInterpolatedParameter(InterpolatedParameter node) =>
|
||||
visitInterpolatedNode(node);
|
||||
T visitInterpolatedSelector(InterpolatedSelector node) =>
|
||||
visitInterpolatedNode(node);
|
||||
T visitInterpolatedStatement(InterpolatedStatement node) =>
|
||||
visitInterpolatedNode(node);
|
||||
T visitInterpolatedDeclaration(InterpolatedDeclaration node) {
|
||||
return visitInterpolatedNode(node);
|
||||
}
|
||||
|
@ -244,6 +243,7 @@ class Program extends Node {
|
|||
void visitChildren(NodeVisitor visitor) {
|
||||
for (Statement statement in body) statement.accept(visitor);
|
||||
}
|
||||
|
||||
Program _clone() => new Program(body);
|
||||
}
|
||||
|
||||
|
@ -260,6 +260,7 @@ class Block extends Statement {
|
|||
void visitChildren(NodeVisitor visitor) {
|
||||
for (Statement statement in statements) statement.accept(visitor);
|
||||
}
|
||||
|
||||
Block _clone() => new Block(statements);
|
||||
}
|
||||
|
||||
|
@ -270,7 +271,10 @@ class ExpressionStatement extends Statement {
|
|||
}
|
||||
|
||||
accept(NodeVisitor visitor) => visitor.visitExpressionStatement(this);
|
||||
void visitChildren(NodeVisitor visitor) { expression.accept(visitor); }
|
||||
void visitChildren(NodeVisitor visitor) {
|
||||
expression.accept(visitor);
|
||||
}
|
||||
|
||||
ExpressionStatement _clone() => new ExpressionStatement(expression);
|
||||
}
|
||||
|
||||
|
@ -290,7 +294,7 @@ class If extends Statement {
|
|||
If(this.condition, this.then, this.otherwise);
|
||||
If.noElse(this.condition, this.then) : this.otherwise = new EmptyStatement();
|
||||
|
||||
bool get hasElse => otherwise is !EmptyStatement;
|
||||
bool get hasElse => otherwise is! EmptyStatement;
|
||||
|
||||
accept(NodeVisitor visitor) => visitor.visitIf(this);
|
||||
|
||||
|
@ -377,7 +381,7 @@ class Do extends Loop {
|
|||
}
|
||||
|
||||
class Continue extends Statement {
|
||||
final String targetLabel; // Can be null.
|
||||
final String targetLabel; // Can be null.
|
||||
|
||||
Continue(this.targetLabel);
|
||||
|
||||
|
@ -388,7 +392,7 @@ class Continue extends Statement {
|
|||
}
|
||||
|
||||
class Break extends Statement {
|
||||
final String targetLabel; // Can be null.
|
||||
final String targetLabel; // Can be null.
|
||||
|
||||
Break(this.targetLabel);
|
||||
|
||||
|
@ -399,7 +403,7 @@ class Break extends Statement {
|
|||
}
|
||||
|
||||
class Return extends Statement {
|
||||
final Expression value; // Can be null.
|
||||
final Expression value; // Can be null.
|
||||
|
||||
Return([this.value = null]);
|
||||
|
||||
|
@ -428,8 +432,8 @@ class Throw extends Statement {
|
|||
|
||||
class Try extends Statement {
|
||||
final Block body;
|
||||
final Catch catchPart; // Can be null if [finallyPart] is non-null.
|
||||
final Block finallyPart; // Can be null if [catchPart] is non-null.
|
||||
final Catch catchPart; // Can be null if [finallyPart] is non-null.
|
||||
final Block finallyPart; // Can be null if [catchPart] is non-null.
|
||||
|
||||
Try(this.body, this.catchPart, this.finallyPart) {
|
||||
assert(catchPart != null || finallyPart != null);
|
||||
|
@ -548,7 +552,7 @@ class LiteralStatement extends Statement {
|
|||
LiteralStatement(this.code);
|
||||
|
||||
accept(NodeVisitor visitor) => visitor.visitLiteralStatement(this);
|
||||
void visitChildren(NodeVisitor visitor) { }
|
||||
void visitChildren(NodeVisitor visitor) {}
|
||||
|
||||
LiteralStatement _clone() => new LiteralStatement(code);
|
||||
}
|
||||
|
@ -577,9 +581,7 @@ abstract class Expression extends Node {
|
|||
Statement toStatement() => new ExpressionStatement(this);
|
||||
}
|
||||
|
||||
abstract class Declaration implements VariableReference {
|
||||
|
||||
}
|
||||
abstract class Declaration implements VariableReference {}
|
||||
|
||||
/// An implementation of [Name] represents a potentially late bound name in
|
||||
/// the generated ast.
|
||||
|
@ -660,11 +662,10 @@ class VariableDeclarationList extends Expression {
|
|||
|
||||
class Assignment extends Expression {
|
||||
final Expression leftHandSide;
|
||||
final String op; // Null, if the assignment is not compound.
|
||||
final Expression value; // May be null, for [VariableInitialization]s.
|
||||
final String op; // Null, if the assignment is not compound.
|
||||
final Expression value; // May be null, for [VariableInitialization]s.
|
||||
|
||||
Assignment(leftHandSide, value)
|
||||
: this.compound(leftHandSide, null, value);
|
||||
Assignment(leftHandSide, value) : this.compound(leftHandSide, null, value);
|
||||
// If `this.op == null` this will be a non-compound assignment.
|
||||
Assignment.compound(this.leftHandSide, this.op, this.value);
|
||||
|
||||
|
@ -679,8 +680,7 @@ class Assignment extends Expression {
|
|||
if (value != null) value.accept(visitor);
|
||||
}
|
||||
|
||||
Assignment _clone() =>
|
||||
new Assignment.compound(leftHandSide, op, value);
|
||||
Assignment _clone() => new Assignment.compound(leftHandSide, op, value);
|
||||
}
|
||||
|
||||
class VariableInitialization extends Assignment {
|
||||
|
@ -721,7 +721,7 @@ class Call extends Expression {
|
|||
List<Expression> arguments;
|
||||
|
||||
Call(this.target, this.arguments,
|
||||
{JavaScriptNodeSourceInformation sourceInformation}) {
|
||||
{JavaScriptNodeSourceInformation sourceInformation}) {
|
||||
this._sourceInformation = sourceInformation;
|
||||
}
|
||||
|
||||
|
@ -840,7 +840,6 @@ class Postfix extends Expression {
|
|||
argument.accept(visitor);
|
||||
}
|
||||
|
||||
|
||||
int get precedenceLevel => UNARY;
|
||||
}
|
||||
|
||||
|
@ -902,6 +901,7 @@ class NamedFunction extends Expression {
|
|||
name.accept(visitor);
|
||||
function.accept(visitor);
|
||||
}
|
||||
|
||||
NamedFunction _clone() => new NamedFunction(name, function);
|
||||
|
||||
int get precedenceLevel => LEFT_HAND_SIDE;
|
||||
|
@ -1074,7 +1074,7 @@ class StringConcatenation extends Literal {
|
|||
}
|
||||
|
||||
class LiteralNumber extends Literal {
|
||||
final String value; // Must be a valid JavaScript number literal.
|
||||
final String value; // Must be a valid JavaScript number literal.
|
||||
|
||||
LiteralNumber(this.value);
|
||||
|
||||
|
@ -1170,8 +1170,7 @@ class InterpolatedExpression extends Expression with InterpolatedNode {
|
|||
|
||||
accept(NodeVisitor visitor) => visitor.visitInterpolatedExpression(this);
|
||||
void visitChildren(NodeVisitor visitor) {}
|
||||
InterpolatedExpression _clone() =>
|
||||
new InterpolatedExpression(nameOrPosition);
|
||||
InterpolatedExpression _clone() => new InterpolatedExpression(nameOrPosition);
|
||||
|
||||
int get precedenceLevel => PRIMARY;
|
||||
}
|
||||
|
@ -1186,11 +1185,15 @@ class InterpolatedLiteral extends Literal with InterpolatedNode {
|
|||
InterpolatedLiteral _clone() => new InterpolatedLiteral(nameOrPosition);
|
||||
}
|
||||
|
||||
class InterpolatedParameter extends Expression with InterpolatedNode
|
||||
class InterpolatedParameter extends Expression
|
||||
with InterpolatedNode
|
||||
implements Parameter {
|
||||
final nameOrPosition;
|
||||
|
||||
String get name { throw "InterpolatedParameter.name must not be invoked"; }
|
||||
String get name {
|
||||
throw "InterpolatedParameter.name must not be invoked";
|
||||
}
|
||||
|
||||
bool get allowRename => false;
|
||||
|
||||
InterpolatedParameter(this.nameOrPosition);
|
||||
|
@ -1225,8 +1228,8 @@ class InterpolatedStatement extends Statement with InterpolatedNode {
|
|||
}
|
||||
|
||||
class InterpolatedDeclaration extends Expression
|
||||
with InterpolatedNode
|
||||
implements Declaration {
|
||||
with InterpolatedNode
|
||||
implements Declaration {
|
||||
final nameOrPosition;
|
||||
|
||||
InterpolatedDeclaration(this.nameOrPosition);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
part of js_ast;
|
||||
|
||||
|
||||
typedef String Renamer(Name);
|
||||
|
||||
class JavaScriptPrintingOptions {
|
||||
|
@ -15,19 +14,20 @@ class JavaScriptPrintingOptions {
|
|||
|
||||
JavaScriptPrintingOptions(
|
||||
{this.shouldCompressOutput: false,
|
||||
this.minifyLocalVariables: false,
|
||||
this.preferSemicolonToNewlineInMinifiedOutput: false,
|
||||
this.renamerForNames: identityRenamer});
|
||||
this.minifyLocalVariables: false,
|
||||
this.preferSemicolonToNewlineInMinifiedOutput: false,
|
||||
this.renamerForNames: identityRenamer});
|
||||
|
||||
static String identityRenamer(Name name) => name.name;
|
||||
}
|
||||
|
||||
|
||||
/// An environment in which JavaScript printing is done. Provides emitting of
|
||||
/// text and pre- and post-visit callbacks.
|
||||
abstract class JavaScriptPrintingContext {
|
||||
/// Signals an error. This should happen only for serious internal errors.
|
||||
void error(String message) { throw message; }
|
||||
void error(String message) {
|
||||
throw message;
|
||||
}
|
||||
|
||||
/// Adds [string] to the output.
|
||||
void emit(String string);
|
||||
|
@ -46,10 +46,8 @@ abstract class JavaScriptPrintingContext {
|
|||
/// [Fun] nodes and is `null` otherwise.
|
||||
///
|
||||
/// [enterNode] is called in post-traversal order.
|
||||
void exitNode(Node node,
|
||||
int startPosition,
|
||||
int endPosition,
|
||||
int closingPosition) {}
|
||||
void exitNode(
|
||||
Node node, int startPosition, int endPosition, int closingPosition) {}
|
||||
}
|
||||
|
||||
/// A simple implementation of [JavaScriptPrintingContext] suitable for tests.
|
||||
|
@ -63,7 +61,6 @@ class SimpleJavaScriptPrintingContext extends JavaScriptPrintingContext {
|
|||
String getText() => buffer.toString();
|
||||
}
|
||||
|
||||
|
||||
class Printer implements NodeVisitor {
|
||||
final JavaScriptPrintingOptions options;
|
||||
final JavaScriptPrintingContext context;
|
||||
|
@ -85,22 +82,21 @@ class Printer implements NodeVisitor {
|
|||
static final identifierCharacterRegExp = new RegExp(r'^[a-zA-Z_0-9$]');
|
||||
static final expressionContinuationRegExp = new RegExp(r'^[-+([]');
|
||||
|
||||
Printer(JavaScriptPrintingOptions options,
|
||||
JavaScriptPrintingContext context)
|
||||
Printer(JavaScriptPrintingOptions options, JavaScriptPrintingContext context)
|
||||
: options = options,
|
||||
context = context,
|
||||
shouldCompressOutput = options.shouldCompressOutput,
|
||||
danglingElseVisitor = new DanglingElseVisitor(context),
|
||||
localNamer = determineRenamer(options.shouldCompressOutput,
|
||||
options.minifyLocalVariables);
|
||||
localNamer = determineRenamer(
|
||||
options.shouldCompressOutput, options.minifyLocalVariables);
|
||||
|
||||
static LocalNamer determineRenamer(bool shouldCompressOutput,
|
||||
bool allowVariableMinification) {
|
||||
static LocalNamer determineRenamer(
|
||||
bool shouldCompressOutput, bool allowVariableMinification) {
|
||||
return (shouldCompressOutput && allowVariableMinification)
|
||||
? new MinifyRenamer() : new IdentityNamer();
|
||||
? new MinifyRenamer()
|
||||
: new IdentityNamer();
|
||||
}
|
||||
|
||||
|
||||
// The current indentation string.
|
||||
String get indentation {
|
||||
// Lazily add new indentation strings as required.
|
||||
|
@ -236,7 +232,7 @@ class Printer implements NodeVisitor {
|
|||
}
|
||||
|
||||
void visitCommaSeparated(List<Node> nodes, int hasRequiredType,
|
||||
{bool newInForInit, bool newAtStatementBegin}) {
|
||||
{bool newInForInit, bool newAtStatementBegin}) {
|
||||
for (int i = 0; i < nodes.length; i++) {
|
||||
if (i != 0) {
|
||||
atStatementBegin = false;
|
||||
|
@ -244,8 +240,7 @@ class Printer implements NodeVisitor {
|
|||
spaceOut();
|
||||
}
|
||||
visitNestedExpression(nodes[i], hasRequiredType,
|
||||
newInForInit: newInForInit,
|
||||
newAtStatementBegin: newAtStatementBegin);
|
||||
newInForInit: newInForInit, newAtStatementBegin: newAtStatementBegin);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,7 +320,7 @@ class Printer implements NodeVisitor {
|
|||
void visitExpressionStatement(ExpressionStatement node) {
|
||||
indent();
|
||||
visitNestedExpression(node.expression, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: true);
|
||||
newInForInit: false, newAtStatementBegin: true);
|
||||
outSemicolonLn();
|
||||
}
|
||||
|
||||
|
@ -353,7 +348,7 @@ class Printer implements NodeVisitor {
|
|||
spaceOut();
|
||||
out("(");
|
||||
visitNestedExpression(node.condition, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
out(")");
|
||||
bool thenWasBlock =
|
||||
blockBody(then, needsSeparation: false, needsNewline: !hasElse);
|
||||
|
@ -371,7 +366,7 @@ class Printer implements NodeVisitor {
|
|||
endNode(elsePart);
|
||||
} else {
|
||||
blockBody(unwrapBlockIfSingleStatement(elsePart),
|
||||
needsSeparation: true, needsNewline: true);
|
||||
needsSeparation: true, needsNewline: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -388,23 +383,23 @@ class Printer implements NodeVisitor {
|
|||
out("(");
|
||||
if (loop.init != null) {
|
||||
visitNestedExpression(loop.init, EXPRESSION,
|
||||
newInForInit: true, newAtStatementBegin: false);
|
||||
newInForInit: true, newAtStatementBegin: false);
|
||||
}
|
||||
out(";");
|
||||
if (loop.condition != null) {
|
||||
spaceOut();
|
||||
visitNestedExpression(loop.condition, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
}
|
||||
out(";");
|
||||
if (loop.update != null) {
|
||||
spaceOut();
|
||||
visitNestedExpression(loop.update, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
}
|
||||
out(")");
|
||||
blockBody(unwrapBlockIfSingleStatement(loop.body),
|
||||
needsSeparation: false, needsNewline: true);
|
||||
needsSeparation: false, needsNewline: true);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -413,14 +408,14 @@ class Printer implements NodeVisitor {
|
|||
spaceOut();
|
||||
out("(");
|
||||
visitNestedExpression(loop.leftHandSide, EXPRESSION,
|
||||
newInForInit: true, newAtStatementBegin: false);
|
||||
newInForInit: true, newAtStatementBegin: false);
|
||||
out(" in");
|
||||
pendingSpace = true;
|
||||
visitNestedExpression(loop.object, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
out(")");
|
||||
blockBody(unwrapBlockIfSingleStatement(loop.body),
|
||||
needsSeparation: false, needsNewline: true);
|
||||
needsSeparation: false, needsNewline: true);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -429,17 +424,17 @@ class Printer implements NodeVisitor {
|
|||
spaceOut();
|
||||
out("(");
|
||||
visitNestedExpression(loop.condition, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
out(")");
|
||||
blockBody(unwrapBlockIfSingleStatement(loop.body),
|
||||
needsSeparation: false, needsNewline: true);
|
||||
needsSeparation: false, needsNewline: true);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitDo(Do loop) {
|
||||
outIndent("do");
|
||||
if (blockBody(unwrapBlockIfSingleStatement(loop.body),
|
||||
needsSeparation: true, needsNewline: false)) {
|
||||
needsSeparation: true, needsNewline: false)) {
|
||||
spaceOut();
|
||||
} else {
|
||||
indent();
|
||||
|
@ -448,7 +443,7 @@ class Printer implements NodeVisitor {
|
|||
spaceOut();
|
||||
out("(");
|
||||
visitNestedExpression(loop.condition, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
out(")");
|
||||
outSemicolonLn();
|
||||
}
|
||||
|
@ -481,7 +476,7 @@ class Printer implements NodeVisitor {
|
|||
outIndent("return");
|
||||
pendingSpace = true;
|
||||
visitNestedExpression(node.value, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
}
|
||||
outSemicolonLn();
|
||||
}
|
||||
|
@ -495,7 +490,7 @@ class Printer implements NodeVisitor {
|
|||
}
|
||||
pendingSpace = true;
|
||||
visitNestedExpression(node.expression, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
outSemicolonLn();
|
||||
}
|
||||
|
||||
|
@ -504,7 +499,7 @@ class Printer implements NodeVisitor {
|
|||
outIndent("throw");
|
||||
pendingSpace = true;
|
||||
visitNestedExpression(node.expression, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
outSemicolonLn();
|
||||
}
|
||||
|
||||
|
@ -531,7 +526,7 @@ class Printer implements NodeVisitor {
|
|||
spaceOut();
|
||||
out("(");
|
||||
visitNestedExpression(node.declaration, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
out(")");
|
||||
blockBody(node.body, needsSeparation: false, needsNewline: false);
|
||||
}
|
||||
|
@ -542,7 +537,7 @@ class Printer implements NodeVisitor {
|
|||
spaceOut();
|
||||
out("(");
|
||||
visitNestedExpression(node.key, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
out(")");
|
||||
spaceOut();
|
||||
outLn("{");
|
||||
|
@ -557,7 +552,7 @@ class Printer implements NodeVisitor {
|
|||
outIndent("case");
|
||||
pendingSpace = true;
|
||||
visitNestedExpression(node.expression, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
outLn(":");
|
||||
if (!node.body.statements.isEmpty) {
|
||||
indentMore();
|
||||
|
@ -598,13 +593,13 @@ class Printer implements NodeVisitor {
|
|||
out(" ");
|
||||
// Name must be a [Decl]. Therefore only test for primary expressions.
|
||||
visitNestedExpression(name, PRIMARY,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
}
|
||||
localNamer.enterScope(vars);
|
||||
out("(");
|
||||
if (fun.params != null) {
|
||||
visitCommaSeparated(fun.params, PRIMARY,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
}
|
||||
out(")");
|
||||
switch (fun.asyncModifier) {
|
||||
|
@ -628,7 +623,6 @@ class Printer implements NodeVisitor {
|
|||
blockOut(fun.body, shouldIndent: false, needsNewline: false);
|
||||
localNamer.leaveScope();
|
||||
return closingPosition;
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -644,18 +638,19 @@ class Printer implements NodeVisitor {
|
|||
}
|
||||
|
||||
visitNestedExpression(Expression node, int requiredPrecedence,
|
||||
{bool newInForInit, bool newAtStatementBegin}) {
|
||||
{bool newInForInit, bool newAtStatementBegin}) {
|
||||
bool needsParentheses =
|
||||
// a - (b + c).
|
||||
(requiredPrecedence != EXPRESSION &&
|
||||
node.precedenceLevel < requiredPrecedence) ||
|
||||
// for (a = (x in o); ... ; ... ) { ... }
|
||||
(newInForInit && node is Binary && node.op == "in") ||
|
||||
// (function() { ... })().
|
||||
// ({a: 2, b: 3}.toString()).
|
||||
(newAtStatementBegin && (node is NamedFunction ||
|
||||
node is Fun ||
|
||||
node is ObjectInitializer));
|
||||
node.precedenceLevel < requiredPrecedence) ||
|
||||
// for (a = (x in o); ... ; ... ) { ... }
|
||||
(newInForInit && node is Binary && node.op == "in") ||
|
||||
// (function() { ... })().
|
||||
// ({a: 2, b: 3}.toString()).
|
||||
(newAtStatementBegin &&
|
||||
(node is NamedFunction ||
|
||||
node is Fun ||
|
||||
node is ObjectInitializer));
|
||||
if (needsParentheses) {
|
||||
inForInit = false;
|
||||
atStatementBegin = false;
|
||||
|
@ -673,14 +668,13 @@ class Printer implements NodeVisitor {
|
|||
visitVariableDeclarationList(VariableDeclarationList list) {
|
||||
out("var ");
|
||||
visitCommaSeparated(list.declarations, ASSIGNMENT,
|
||||
newInForInit: inForInit, newAtStatementBegin: false);
|
||||
newInForInit: inForInit, newAtStatementBegin: false);
|
||||
}
|
||||
|
||||
@override
|
||||
visitAssignment(Assignment assignment) {
|
||||
visitNestedExpression(assignment.leftHandSide, CALL,
|
||||
newInForInit: inForInit,
|
||||
newAtStatementBegin: atStatementBegin);
|
||||
newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
|
||||
if (assignment.value != null) {
|
||||
spaceOut();
|
||||
String op = assignment.op;
|
||||
|
@ -688,8 +682,7 @@ class Printer implements NodeVisitor {
|
|||
out("=");
|
||||
spaceOut();
|
||||
visitNestedExpression(assignment.value, ASSIGNMENT,
|
||||
newInForInit: inForInit,
|
||||
newAtStatementBegin: false);
|
||||
newInForInit: inForInit, newAtStatementBegin: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -701,40 +694,38 @@ class Printer implements NodeVisitor {
|
|||
@override
|
||||
visitConditional(Conditional cond) {
|
||||
visitNestedExpression(cond.condition, LOGICAL_OR,
|
||||
newInForInit: inForInit,
|
||||
newAtStatementBegin: atStatementBegin);
|
||||
newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
|
||||
spaceOut();
|
||||
out("?");
|
||||
spaceOut();
|
||||
// The then part is allowed to have an 'in'.
|
||||
visitNestedExpression(cond.then, ASSIGNMENT,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
spaceOut();
|
||||
out(":");
|
||||
spaceOut();
|
||||
visitNestedExpression(cond.otherwise, ASSIGNMENT,
|
||||
newInForInit: inForInit, newAtStatementBegin: false);
|
||||
newInForInit: inForInit, newAtStatementBegin: false);
|
||||
}
|
||||
|
||||
@override
|
||||
visitNew(New node) {
|
||||
out("new ");
|
||||
visitNestedExpression(node.target, LEFT_HAND_SIDE,
|
||||
newInForInit: inForInit, newAtStatementBegin: false);
|
||||
newInForInit: inForInit, newAtStatementBegin: false);
|
||||
out("(");
|
||||
visitCommaSeparated(node.arguments, ASSIGNMENT,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
out(")");
|
||||
}
|
||||
|
||||
@override
|
||||
visitCall(Call call) {
|
||||
visitNestedExpression(call.target, CALL,
|
||||
newInForInit: inForInit,
|
||||
newAtStatementBegin: atStatementBegin);
|
||||
newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
|
||||
out("(");
|
||||
visitCommaSeparated(call.arguments, ASSIGNMENT,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
out(")");
|
||||
}
|
||||
|
||||
|
@ -745,7 +736,7 @@ class Printer implements NodeVisitor {
|
|||
String op = binary.op;
|
||||
int leftPrecedenceRequirement;
|
||||
int rightPrecedenceRequirement;
|
||||
bool leftSpace = true; // left<HERE>op right
|
||||
bool leftSpace = true; // left<HERE>op right
|
||||
switch (op) {
|
||||
case ',':
|
||||
// x, (y, z) <=> (x, y), z.
|
||||
|
@ -822,8 +813,7 @@ class Printer implements NodeVisitor {
|
|||
}
|
||||
|
||||
visitNestedExpression(left, leftPrecedenceRequirement,
|
||||
newInForInit: inForInit,
|
||||
newAtStatementBegin: atStatementBegin);
|
||||
newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
|
||||
|
||||
if (op == "in" || op == "instanceof") {
|
||||
// There are cases where the space is not required but without further
|
||||
|
@ -837,8 +827,7 @@ class Printer implements NodeVisitor {
|
|||
spaceOut();
|
||||
}
|
||||
visitNestedExpression(right, rightPrecedenceRequirement,
|
||||
newInForInit: inForInit,
|
||||
newAtStatementBegin: false);
|
||||
newInForInit: inForInit, newAtStatementBegin: false);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -867,14 +856,13 @@ class Printer implements NodeVisitor {
|
|||
out(op);
|
||||
}
|
||||
visitNestedExpression(unary.argument, UNARY,
|
||||
newInForInit: inForInit, newAtStatementBegin: false);
|
||||
newInForInit: inForInit, newAtStatementBegin: false);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitPostfix(Postfix postfix) {
|
||||
visitNestedExpression(postfix.argument, CALL,
|
||||
newInForInit: inForInit,
|
||||
newAtStatementBegin: atStatementBegin);
|
||||
newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
|
||||
out(postfix.op);
|
||||
}
|
||||
|
||||
|
@ -909,10 +897,10 @@ class Printer implements NodeVisitor {
|
|||
// TODO(floitsch): allow more characters.
|
||||
int charCode = field.codeUnitAt(i);
|
||||
if (!(charCodes.$a <= charCode && charCode <= charCodes.$z ||
|
||||
charCodes.$A <= charCode && charCode <= charCodes.$Z ||
|
||||
charCode == charCodes.$$ ||
|
||||
charCode == charCodes.$_ ||
|
||||
i != 1 && isDigit(charCode))) {
|
||||
charCodes.$A <= charCode && charCode <= charCodes.$Z ||
|
||||
charCode == charCodes.$$ ||
|
||||
charCode == charCodes.$_ ||
|
||||
i != 1 && isDigit(charCode))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -927,8 +915,7 @@ class Printer implements NodeVisitor {
|
|||
@override
|
||||
void visitAccess(PropertyAccess access) {
|
||||
visitNestedExpression(access.receiver, CALL,
|
||||
newInForInit: inForInit,
|
||||
newAtStatementBegin: atStatementBegin);
|
||||
newInForInit: inForInit, newAtStatementBegin: atStatementBegin);
|
||||
Node selector = access.selector;
|
||||
if (selector is LiteralString) {
|
||||
LiteralString selectorString = selector;
|
||||
|
@ -957,7 +944,7 @@ class Printer implements NodeVisitor {
|
|||
}
|
||||
out("[");
|
||||
visitNestedExpression(selector, EXPRESSION,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
out("]");
|
||||
}
|
||||
|
||||
|
@ -1051,7 +1038,7 @@ class Printer implements NodeVisitor {
|
|||
}
|
||||
if (i != 0) spaceOut();
|
||||
visitNestedExpression(element, ASSIGNMENT,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
// We can skip the trailing "," for the last element (since it's not
|
||||
// an array hole).
|
||||
if (i != elements.length - 1) out(",");
|
||||
|
@ -1070,8 +1057,7 @@ class Printer implements NodeVisitor {
|
|||
// property. Ideally, we would use a proper pretty-printer to make the
|
||||
// decision based on layout.
|
||||
bool exitOneLinerMode(Expression value) {
|
||||
return
|
||||
value is Fun ||
|
||||
return value is Fun ||
|
||||
value is ArrayInitializer && value.elements.any((e) => e is Fun);
|
||||
}
|
||||
|
||||
|
@ -1122,7 +1108,7 @@ class Printer implements NodeVisitor {
|
|||
out(":");
|
||||
spaceOut();
|
||||
visitNestedExpression(node.value, ASSIGNMENT,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1205,12 +1191,13 @@ class Printer implements NodeVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
class OrderedSet<T> {
|
||||
final Set<T> set;
|
||||
final List<T> list;
|
||||
|
||||
OrderedSet() : set = new Set<T>(), list = <T>[];
|
||||
OrderedSet()
|
||||
: set = new Set<T>(),
|
||||
list = <T>[];
|
||||
|
||||
void add(T x) {
|
||||
if (set.add(x)) {
|
||||
|
@ -1235,9 +1222,10 @@ class VarCollector extends BaseVisitor {
|
|||
static final String disableVariableMinificationPattern = "::norenaming::";
|
||||
static final String enableVariableMinificationPattern = "::dorenaming::";
|
||||
|
||||
VarCollector() : nested = false,
|
||||
vars = new OrderedSet<String>(),
|
||||
params = new OrderedSet<String>();
|
||||
VarCollector()
|
||||
: nested = false,
|
||||
vars = new OrderedSet<String>(),
|
||||
params = new OrderedSet<String>();
|
||||
|
||||
void forEachVar(void fn(String v)) => vars.forEach(fn);
|
||||
void forEachParam(void fn(String p)) => params.forEach(fn);
|
||||
|
@ -1284,7 +1272,6 @@ class VarCollector extends BaseVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true, if the given node must be wrapped into braces when used
|
||||
* as then-statement in an [If] that has an else branch.
|
||||
|
@ -1308,6 +1295,7 @@ class DanglingElseVisitor extends BaseVisitor<bool> {
|
|||
if (!node.hasElse) return true;
|
||||
return node.otherwise.accept(this);
|
||||
}
|
||||
|
||||
bool visitFor(For node) => node.body.accept(this);
|
||||
bool visitForIn(ForIn node) => node.body.accept(this);
|
||||
bool visitWhile(While node) => node.body.accept(this);
|
||||
|
@ -1323,19 +1311,18 @@ class DanglingElseVisitor extends BaseVisitor<bool> {
|
|||
return node.catchPart.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool visitCatch(Catch node) => node.body.accept(this);
|
||||
bool visitSwitch(Switch node) => false;
|
||||
bool visitCase(Case node) => false;
|
||||
bool visitDefault(Default node) => false;
|
||||
bool visitFunctionDeclaration(FunctionDeclaration node) => false;
|
||||
bool visitLabeledStatement(LabeledStatement node)
|
||||
=> node.body.accept(this);
|
||||
bool visitLabeledStatement(LabeledStatement node) => node.body.accept(this);
|
||||
bool visitLiteralStatement(LiteralStatement node) => true;
|
||||
|
||||
bool visitExpression(Expression node) => false;
|
||||
}
|
||||
|
||||
|
||||
abstract class LocalNamer {
|
||||
String getName(String oldName);
|
||||
String declareVariable(String oldName);
|
||||
|
@ -1344,7 +1331,6 @@ abstract class LocalNamer {
|
|||
void leaveScope();
|
||||
}
|
||||
|
||||
|
||||
class IdentityNamer implements LocalNamer {
|
||||
String getName(String oldName) => oldName;
|
||||
String declareVariable(String oldName) => oldName;
|
||||
|
@ -1353,7 +1339,6 @@ class IdentityNamer implements LocalNamer {
|
|||
void leaveScope() {}
|
||||
}
|
||||
|
||||
|
||||
class MinifyRenamer implements LocalNamer {
|
||||
final List<Map<String, String>> maps = [];
|
||||
final List<int> parameterNumberStack = [];
|
||||
|
@ -1392,9 +1377,9 @@ class MinifyRenamer implements LocalNamer {
|
|||
static const DIGITS = 10;
|
||||
|
||||
static int nthLetter(int n) {
|
||||
return (n < LOWER_CASE_LETTERS) ?
|
||||
charCodes.$a + n :
|
||||
charCodes.$A + n - LOWER_CASE_LETTERS;
|
||||
return (n < LOWER_CASE_LETTERS)
|
||||
? charCodes.$a + n
|
||||
: charCodes.$A + n - LOWER_CASE_LETTERS;
|
||||
}
|
||||
|
||||
// Parameters go from a to z and variables go from z to a. This makes each
|
||||
|
|
|
@ -10,7 +10,6 @@ class TemplateManager {
|
|||
|
||||
TemplateManager();
|
||||
|
||||
|
||||
Template lookupExpressionTemplate(String source) {
|
||||
return expressionTemplates[source];
|
||||
}
|
||||
|
@ -55,13 +54,15 @@ class Template {
|
|||
bool get isPositional => holeNames == null;
|
||||
|
||||
Template(this.source, this.ast,
|
||||
{this.isExpression: true, this.forceCopy: false}) {
|
||||
{this.isExpression: true, this.forceCopy: false}) {
|
||||
assert(this.isExpression ? ast is Expression : ast is Statement);
|
||||
_compile();
|
||||
}
|
||||
|
||||
Template.withExpressionResult(this.ast)
|
||||
: source = null, isExpression = true, forceCopy = false {
|
||||
: source = null,
|
||||
isExpression = true,
|
||||
forceCopy = false {
|
||||
assert(ast is Expression);
|
||||
assert(_checkNoPlaceholders());
|
||||
positionalArgumentCount = 0;
|
||||
|
@ -69,7 +70,9 @@ class Template {
|
|||
}
|
||||
|
||||
Template.withStatementResult(this.ast)
|
||||
: source = null, isExpression = false, forceCopy = false {
|
||||
: source = null,
|
||||
isExpression = false,
|
||||
forceCopy = false {
|
||||
assert(ast is Statement);
|
||||
assert(_checkNoPlaceholders());
|
||||
positionalArgumentCount = 0;
|
||||
|
@ -89,7 +92,7 @@ class Template {
|
|||
instantiator = generator.compile(ast);
|
||||
positionalArgumentCount = generator.analysis.count;
|
||||
Set<String> names = generator.analysis.holeNames;
|
||||
holeNames = names.toList(growable:false);
|
||||
holeNames = names.toList(growable: false);
|
||||
}
|
||||
|
||||
/// Instantiates the template with the given [arguments].
|
||||
|
@ -128,14 +131,12 @@ class Template {
|
|||
*/
|
||||
typedef Node Instantiator(var arguments);
|
||||
|
||||
|
||||
/**
|
||||
* InstantiatorGeneratorVisitor compiles a template. This class compiles a tree
|
||||
* containing [InterpolatedNode]s into a function that will create a copy of the
|
||||
* tree with the interpolated nodes substituted with provided values.
|
||||
*/
|
||||
class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
||||
|
||||
final bool forceCopy;
|
||||
|
||||
InterpolatedNodeAnalysis analysis = new InterpolatedNodeAnalysis();
|
||||
|
@ -222,6 +223,7 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
return error('Interpolated value #$nameOrPosition is not '
|
||||
'an Expression or List of Expressions: $value');
|
||||
}
|
||||
|
||||
if (value is Iterable) return value.map(toExpression);
|
||||
return toExpression(value);
|
||||
};
|
||||
|
@ -247,8 +249,9 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
if (item is Parameter) return item;
|
||||
if (item is String) return new Parameter(item);
|
||||
return error('Interpolated value #$nameOrPosition is not a Parameter or'
|
||||
' List of Parameters: $value');
|
||||
' List of Parameters: $value');
|
||||
}
|
||||
|
||||
if (value is Iterable) return value.map(toParameter);
|
||||
return toParameter(value);
|
||||
};
|
||||
|
@ -283,10 +286,12 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
var value = arguments[nameOrPosition];
|
||||
Statement toStatement(item) {
|
||||
if (item is Statement) return item;
|
||||
if (item is Expression) return item.toStatement();;
|
||||
if (item is Expression) return item.toStatement();
|
||||
;
|
||||
return error('Interpolated value #$nameOrPosition is not '
|
||||
'a Statement or List of Statements: $value');
|
||||
'a Statement or List of Statements: $value');
|
||||
}
|
||||
|
||||
if (value is Iterable) return value.map(toStatement);
|
||||
return toStatement(value);
|
||||
};
|
||||
|
@ -306,6 +311,7 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
statements.add(node.toStatement());
|
||||
}
|
||||
}
|
||||
|
||||
for (Instantiator instantiator in instantiators) {
|
||||
add(instantiator(arguments));
|
||||
}
|
||||
|
@ -327,6 +333,7 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
statements.add(node.toStatement());
|
||||
}
|
||||
}
|
||||
|
||||
for (Instantiator instantiator in instantiators) {
|
||||
add(instantiator(arguments));
|
||||
}
|
||||
|
@ -360,11 +367,13 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
var value = arguments[nameOrPosition];
|
||||
if (value is bool) return value;
|
||||
if (value is Expression) return value;
|
||||
if (value is String) return convertStringToVariableUse(value);;
|
||||
if (value is String) return convertStringToVariableUse(value);
|
||||
;
|
||||
error('Interpolated value #$nameOrPosition '
|
||||
'is not an Expression: $value');
|
||||
'is not an Expression: $value');
|
||||
};
|
||||
}
|
||||
|
||||
var makeCondition = compileCondition(node.condition);
|
||||
Instantiator makeThen = visit(node.then);
|
||||
Instantiator makeOtherwise = visit(node.otherwise);
|
||||
|
@ -377,10 +386,7 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
return makeOtherwise(arguments);
|
||||
}
|
||||
}
|
||||
return new If(
|
||||
condition,
|
||||
makeThen(arguments),
|
||||
makeOtherwise(arguments));
|
||||
return new If(condition, makeThen(arguments), makeOtherwise(arguments));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -389,9 +395,7 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
Instantiator makeThen = visit(node.then);
|
||||
Instantiator makeOtherwise = visit(node.otherwise);
|
||||
return (arguments) {
|
||||
return new If(
|
||||
makeCondition(arguments),
|
||||
makeThen(arguments),
|
||||
return new If(makeCondition(arguments), makeThen(arguments),
|
||||
makeOtherwise(arguments));
|
||||
};
|
||||
}
|
||||
|
@ -402,9 +406,8 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
Instantiator makeUpdate = visitNullable(node.update);
|
||||
Instantiator makeBody = visit(node.body);
|
||||
return (arguments) {
|
||||
return new For(
|
||||
makeInit(arguments), makeCondition(arguments), makeUpdate(arguments),
|
||||
makeBody(arguments));
|
||||
return new For(makeInit(arguments), makeCondition(arguments),
|
||||
makeUpdate(arguments), makeBody(arguments));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -413,9 +416,7 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
Instantiator makeObject = visit(node.object);
|
||||
Instantiator makeBody = visit(node.body);
|
||||
return (arguments) {
|
||||
return new ForIn(
|
||||
makeLeftHandSide(arguments),
|
||||
makeObject(arguments),
|
||||
return new ForIn(makeLeftHandSide(arguments), makeObject(arguments),
|
||||
makeBody(arguments));
|
||||
};
|
||||
}
|
||||
|
@ -453,7 +454,8 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
|
||||
Instantiator visitDartYield(DartYield node) {
|
||||
Instantiator makeExpression = visit(node.expression);
|
||||
return (arguments) => new DartYield(makeExpression(arguments), node.hasStar);
|
||||
return (arguments) =>
|
||||
new DartYield(makeExpression(arguments), node.hasStar);
|
||||
}
|
||||
|
||||
Instantiator visitThrow(Throw node) {
|
||||
|
@ -472,17 +474,19 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
Instantiator visitCatch(Catch node) {
|
||||
Instantiator makeDeclaration = visit(node.declaration);
|
||||
Instantiator makeBody = visit(node.body);
|
||||
return (arguments) => new Catch(
|
||||
makeDeclaration(arguments), makeBody(arguments));
|
||||
return (arguments) =>
|
||||
new Catch(makeDeclaration(arguments), makeBody(arguments));
|
||||
}
|
||||
|
||||
Instantiator visitSwitch(Switch node) {
|
||||
Instantiator makeKey = visit(node.key);
|
||||
Iterable<Instantiator> makeCases = node.cases.map(visit);
|
||||
return (arguments) {
|
||||
return new Switch(makeKey(arguments),
|
||||
makeCases.map((Instantiator makeCase) => makeCase(arguments))
|
||||
.toList());
|
||||
return new Switch(
|
||||
makeKey(arguments),
|
||||
makeCases
|
||||
.map((Instantiator makeCase) => makeCase(arguments))
|
||||
.toList());
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -537,9 +541,7 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
Instantiator makeValue = visitNullable(node.value);
|
||||
return (arguments) {
|
||||
return new Assignment.compound(
|
||||
makeLeftHandSide(arguments),
|
||||
op,
|
||||
makeValue(arguments));
|
||||
makeLeftHandSide(arguments), op, makeValue(arguments));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -556,10 +558,8 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
Instantiator makeCondition = visit(cond.condition);
|
||||
Instantiator makeThen = visit(cond.then);
|
||||
Instantiator makeOtherwise = visit(cond.otherwise);
|
||||
return (arguments) => new Conditional(
|
||||
makeCondition(arguments),
|
||||
makeThen(arguments),
|
||||
makeOtherwise(arguments));
|
||||
return (arguments) => new Conditional(makeCondition(arguments),
|
||||
makeThen(arguments), makeOtherwise(arguments));
|
||||
}
|
||||
|
||||
Instantiator visitNew(New node) =>
|
||||
|
@ -658,8 +658,7 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
|
||||
Instantiator visitDeferredNumber(DeferredNumber node) => same(node);
|
||||
|
||||
Instantiator visitDeferredString(DeferredString node) =>
|
||||
(arguments) => node;
|
||||
Instantiator visitDeferredString(DeferredString node) => (arguments) => node;
|
||||
|
||||
Instantiator visitLiteralBool(LiteralBool node) =>
|
||||
(arguments) => new LiteralBool(node.value);
|
||||
|
@ -674,9 +673,8 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
(arguments) => new LiteralNull();
|
||||
|
||||
Instantiator visitStringConcatenation(StringConcatenation node) {
|
||||
List<Instantiator> partMakers = node.parts
|
||||
.map(visit)
|
||||
.toList(growable: false);
|
||||
List<Instantiator> partMakers =
|
||||
node.parts.map(visit).toList(growable: false);
|
||||
return (arguments) {
|
||||
List<Literal> parts = partMakers
|
||||
.map((Instantiator instantiator) => instantiator(arguments))
|
||||
|
@ -689,9 +687,8 @@ class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {
|
|||
|
||||
Instantiator visitArrayInitializer(ArrayInitializer node) {
|
||||
// TODO(sra): Implement splicing?
|
||||
List<Instantiator> elementMakers = node.elements
|
||||
.map(visit)
|
||||
.toList(growable: false);
|
||||
List<Instantiator> elementMakers =
|
||||
node.elements.map(visit).toList(growable: false);
|
||||
return (arguments) {
|
||||
List<Expression> elements = elementMakers
|
||||
.map((Instantiator instantiator) => instantiator(arguments))
|
||||
|
|
|
@ -25,9 +25,7 @@ class TestCase {
|
|||
/// Map from template names to the inserted values.
|
||||
final Map<String, String> environment;
|
||||
|
||||
const TestCase(
|
||||
this.data,
|
||||
[this.environment = const {}]);
|
||||
const TestCase(this.data, [this.environment = const {}]);
|
||||
}
|
||||
|
||||
const List<TestCase> DATA = const <TestCase>[
|
||||
|
@ -44,12 +42,11 @@ function(a, b) {
|
|||
function(a, b) {
|
||||
return null;
|
||||
@0}""",
|
||||
TestMode.EXIT: """
|
||||
TestMode.EXIT: """
|
||||
function(a@1, b@2) {
|
||||
return null@5;
|
||||
@4}@3@0"""
|
||||
}),
|
||||
|
||||
const TestCase(const {
|
||||
TestMode.NONE: """
|
||||
function() {
|
||||
|
@ -108,7 +105,6 @@ function() {
|
|||
@26 }@22
|
||||
@20}@1@0""",
|
||||
}),
|
||||
|
||||
const TestCase(const {
|
||||
TestMode.NONE: """
|
||||
function() {
|
||||
|
@ -125,13 +121,12 @@ function() {
|
|||
function foo() {
|
||||
@3}
|
||||
@0}""",
|
||||
TestMode.EXIT: """
|
||||
TestMode.EXIT: """
|
||||
function() {
|
||||
function foo@4() {
|
||||
}@5@3
|
||||
@2}@1@0"""
|
||||
}),
|
||||
|
||||
const TestCase(const {
|
||||
TestMode.INPUT: """
|
||||
function() {
|
||||
|
@ -153,20 +148,21 @@ function() {
|
|||
a.b;
|
||||
[1,, 2];
|
||||
@0}""",
|
||||
TestMode.EXIT: """
|
||||
TestMode.EXIT: """
|
||||
function() {
|
||||
a@4.b@5@3;
|
||||
@2 [1@8,,@9 2@10]@7;
|
||||
@6}@1@0""",
|
||||
}),
|
||||
|
||||
const TestCase(const {
|
||||
TestMode.INPUT: "a.#nameTemplate = #nameTemplate",
|
||||
TestMode.NONE: "a.nameValue = nameValue",
|
||||
TestMode.ENTER: "@0@1@2a.@3nameValue = @3nameValue",
|
||||
TestMode.DELIMITER: "a.nameValue = nameValue",
|
||||
TestMode.EXIT: "a@2.nameValue@3@1 = nameValue@3@0",
|
||||
}, const {'nameTemplate': 'nameValue'}),
|
||||
}, const {
|
||||
'nameTemplate': 'nameValue'
|
||||
}),
|
||||
];
|
||||
|
||||
class FixedName extends Name {
|
||||
|
@ -221,10 +217,8 @@ class Context extends SimpleJavaScriptPrintingContext {
|
|||
}
|
||||
}
|
||||
|
||||
void exitNode(Node node,
|
||||
int startPosition,
|
||||
int endPosition,
|
||||
int delimiterPosition) {
|
||||
void exitNode(
|
||||
Node node, int startPosition, int endPosition, int delimiterPosition) {
|
||||
int value = id(node);
|
||||
if (mode == TestMode.DELIMITER && delimiterPosition != null) {
|
||||
tagMap.putIfAbsent(delimiterPosition, () => []).add(tag(value));
|
||||
|
|
|
@ -23,127 +23,145 @@ void main() {
|
|||
}
|
||||
|
||||
test('simple', () {
|
||||
check('', [$DQ, $DQ]);
|
||||
check('a', [$DQ, $a, $DQ]);
|
||||
});
|
||||
check('', [$DQ, $DQ]);
|
||||
check('a', [$DQ, $a, $DQ]);
|
||||
});
|
||||
|
||||
test('simple-escapes', () {
|
||||
check([$BS], [$DQ, $BACKSLASH, $b, $DQ]);
|
||||
check([$BS], [$DQ, $BACKSLASH, $b, $DQ], ascii: true);
|
||||
check([$BS], [$DQ, $BACKSLASH, $b, $DQ], utf8: true);
|
||||
check([$BS], [$DQ, $BACKSLASH, $b, $DQ]);
|
||||
check([$BS], [$DQ, $BACKSLASH, $b, $DQ], ascii: true);
|
||||
check([$BS], [$DQ, $BACKSLASH, $b, $DQ], utf8: true);
|
||||
|
||||
check([$LF], [$DQ, $BACKSLASH, $n, $DQ]);
|
||||
check([$LF], [$DQ, $BACKSLASH, $n, $DQ], ascii: true);
|
||||
check([$LF], [$DQ, $BACKSLASH, $n, $DQ], utf8: true);
|
||||
check([$LF], [$DQ, $BACKSLASH, $n, $DQ]);
|
||||
check([$LF], [$DQ, $BACKSLASH, $n, $DQ], ascii: true);
|
||||
check([$LF], [$DQ, $BACKSLASH, $n, $DQ], utf8: true);
|
||||
|
||||
check([$FF], [$DQ, $FF, $DQ]);
|
||||
check([$FF], [$DQ, $BACKSLASH, $f, $DQ], ascii: true);
|
||||
check([$FF], [$DQ, $BACKSLASH, $f, $DQ], utf8: true);
|
||||
check([$FF], [$DQ, $FF, $DQ]);
|
||||
check([$FF], [$DQ, $BACKSLASH, $f, $DQ], ascii: true);
|
||||
check([$FF], [$DQ, $BACKSLASH, $f, $DQ], utf8: true);
|
||||
|
||||
check([$CR], [$DQ, $BACKSLASH, $r, $DQ]);
|
||||
check([$CR], [$DQ, $BACKSLASH, $r, $DQ], ascii: true);
|
||||
check([$CR], [$DQ, $BACKSLASH, $r, $DQ], utf8: true);
|
||||
check([$CR], [$DQ, $BACKSLASH, $r, $DQ]);
|
||||
check([$CR], [$DQ, $BACKSLASH, $r, $DQ], ascii: true);
|
||||
check([$CR], [$DQ, $BACKSLASH, $r, $DQ], utf8: true);
|
||||
|
||||
check([$TAB], [$DQ, $BACKSLASH, $t, $DQ]);
|
||||
check([$TAB], [$DQ, $BACKSLASH, $t, $DQ], ascii: true);
|
||||
check([$TAB], [$DQ, $BACKSLASH, $t, $DQ], utf8: true);
|
||||
check([$TAB], [$DQ, $BACKSLASH, $t, $DQ]);
|
||||
check([$TAB], [$DQ, $BACKSLASH, $t, $DQ], ascii: true);
|
||||
check([$TAB], [$DQ, $BACKSLASH, $t, $DQ], utf8: true);
|
||||
|
||||
check([$VTAB], [$DQ, $BACKSLASH, $v, $DQ]);
|
||||
check([$VTAB], [$DQ, $BACKSLASH, $v, $DQ], ascii: true);
|
||||
check([$VTAB], [$DQ, $BACKSLASH, $v, $DQ], utf8: true);
|
||||
});
|
||||
check([$VTAB], [$DQ, $BACKSLASH, $v, $DQ]);
|
||||
check([$VTAB], [$DQ, $BACKSLASH, $v, $DQ], ascii: true);
|
||||
check([$VTAB], [$DQ, $BACKSLASH, $v, $DQ], utf8: true);
|
||||
});
|
||||
|
||||
test('unnamed-control-codes-escapes', () {
|
||||
check([0, 1, 2, 3], [$DQ, 0, 1, 2, 3, $DQ]);
|
||||
check([0, 1, 2, 3], r'''"\x00\x01\x02\x03"''', ascii: true);
|
||||
check([0, 1, 2, 3], [$DQ, 0, 1, 2, 3, $DQ], utf8: true);
|
||||
});
|
||||
|
||||
check([0, 1, 2, 3], [$DQ, 0, 1, 2, 3, $DQ]);
|
||||
check([0, 1, 2, 3], r'''"\x00\x01\x02\x03"''', ascii: true);
|
||||
check([0, 1, 2, 3], [$DQ, 0, 1, 2, 3, $DQ], utf8: true);
|
||||
});
|
||||
|
||||
test('line-separator', () {
|
||||
// Legacy escaper is broken.
|
||||
// check([$LS], [$DQ, $BACKSLASH, $u, $2, $0, $2, $8, $DQ]);
|
||||
check([$LS], [$DQ, $BACKSLASH, $u, $2, $0, $2, $8, $DQ], ascii: true);
|
||||
check([$LS], [$DQ, $BACKSLASH, $u, $2, $0, $2, $8, $DQ], utf8: true);
|
||||
});
|
||||
// Legacy escaper is broken.
|
||||
// check([$LS], [$DQ, $BACKSLASH, $u, $2, $0, $2, $8, $DQ]);
|
||||
check([$LS], [$DQ, $BACKSLASH, $u, $2, $0, $2, $8, $DQ], ascii: true);
|
||||
check([$LS], [$DQ, $BACKSLASH, $u, $2, $0, $2, $8, $DQ], utf8: true);
|
||||
});
|
||||
|
||||
test('page-separator', () {
|
||||
// Legacy escaper is broken.
|
||||
// check([$PS], [$DQ, $BACKSLASH, $u, $2, $0, $2, $9, $DQ]);
|
||||
check([$PS], [$DQ, $BACKSLASH, $u, $2, $0, $2, $9, $DQ], ascii: true);
|
||||
check([$PS], [$DQ, $BACKSLASH, $u, $2, $0, $2, $9, $DQ], utf8: true);
|
||||
});
|
||||
// Legacy escaper is broken.
|
||||
// check([$PS], [$DQ, $BACKSLASH, $u, $2, $0, $2, $9, $DQ]);
|
||||
check([$PS], [$DQ, $BACKSLASH, $u, $2, $0, $2, $9, $DQ], ascii: true);
|
||||
check([$PS], [$DQ, $BACKSLASH, $u, $2, $0, $2, $9, $DQ], utf8: true);
|
||||
});
|
||||
|
||||
test('legacy-escaper-is-broken', () {
|
||||
check([$LS], [$DQ, 0x2028, $DQ]);
|
||||
check([$PS], [$DQ, 0x2029, $DQ]);
|
||||
});
|
||||
check([$LS], [$DQ, 0x2028, $DQ]);
|
||||
check([$PS], [$DQ, 0x2029, $DQ]);
|
||||
});
|
||||
|
||||
test('choose-quotes', () {
|
||||
check('\'', [$DQ, $SQ, $DQ]);
|
||||
check('"', [$SQ, $DQ, $SQ], ascii: true);
|
||||
check("'", [$DQ, $SQ, $DQ], ascii: true);
|
||||
// Legacy always double-quotes
|
||||
check([$DQ, $DQ, $SQ],
|
||||
[$DQ, $BACKSLASH, $DQ, $BACKSLASH, $DQ, $SQ, $DQ]);
|
||||
// Using single quotes saves us one backslash:
|
||||
check([$DQ, $DQ, $SQ],
|
||||
[$SQ, $DQ, $DQ, $BACKSLASH, $SQ, $SQ],
|
||||
ascii: true);
|
||||
check([$DQ, $SQ, $SQ],
|
||||
[$DQ, $BACKSLASH, $DQ, $SQ, $SQ, $DQ],
|
||||
ascii: true);
|
||||
});
|
||||
check('\'', [$DQ, $SQ, $DQ]);
|
||||
check('"', [$SQ, $DQ, $SQ], ascii: true);
|
||||
check("'", [$DQ, $SQ, $DQ], ascii: true);
|
||||
// Legacy always double-quotes
|
||||
check([$DQ, $DQ, $SQ], [$DQ, $BACKSLASH, $DQ, $BACKSLASH, $DQ, $SQ, $DQ]);
|
||||
// Using single quotes saves us one backslash:
|
||||
check([$DQ, $DQ, $SQ], [$SQ, $DQ, $DQ, $BACKSLASH, $SQ, $SQ], ascii: true);
|
||||
check([$DQ, $SQ, $SQ], [$DQ, $BACKSLASH, $DQ, $SQ, $SQ, $DQ], ascii: true);
|
||||
});
|
||||
|
||||
test('u1234', () {
|
||||
check('\u1234', [$DQ, 0x1234, $DQ]);
|
||||
check('\u1234', [$DQ, $BACKSLASH, $u, $1, $2, $3, $4, $DQ], ascii: true);
|
||||
check('\u1234', [$DQ, 0x1234, $DQ], utf8: true);
|
||||
});
|
||||
check('\u1234', [$DQ, 0x1234, $DQ]);
|
||||
check('\u1234', [$DQ, $BACKSLASH, $u, $1, $2, $3, $4, $DQ], ascii: true);
|
||||
check('\u1234', [$DQ, 0x1234, $DQ], utf8: true);
|
||||
});
|
||||
|
||||
test('u12345', () {
|
||||
check([0x12345], [$DQ, 55304, 57157, $DQ]);
|
||||
// TODO: ES6 option:
|
||||
//check([0x12345],
|
||||
// [$DQ, $BACKSLASH, $u, $LCURLY, $1, $2, $3, $4, $5, $RCURLY, $DQ],
|
||||
// ascii: true);
|
||||
check([0x12345], r'''"\ud808\udf45"''', ascii: true);
|
||||
check([0x12345],
|
||||
[$DQ, $BACKSLASH, $u, $d, $8, $0, $8,
|
||||
$BACKSLASH, $u, $d, $f, $4, $5, $DQ],
|
||||
ascii: true);
|
||||
check([0x12345], [$DQ, 55304, 57157, $DQ], utf8: true);
|
||||
});
|
||||
check([0x12345], [$DQ, 55304, 57157, $DQ]);
|
||||
// TODO: ES6 option:
|
||||
//check([0x12345],
|
||||
// [$DQ, $BACKSLASH, $u, $LCURLY, $1, $2, $3, $4, $5, $RCURLY, $DQ],
|
||||
// ascii: true);
|
||||
check([0x12345], r'''"\ud808\udf45"''', ascii: true);
|
||||
check([
|
||||
0x12345
|
||||
], [
|
||||
$DQ,
|
||||
$BACKSLASH,
|
||||
$u,
|
||||
$d,
|
||||
$8,
|
||||
$0,
|
||||
$8,
|
||||
$BACKSLASH,
|
||||
$u,
|
||||
$d,
|
||||
$f,
|
||||
$4,
|
||||
$5,
|
||||
$DQ
|
||||
], ascii: true);
|
||||
check([0x12345], [$DQ, 55304, 57157, $DQ], utf8: true);
|
||||
});
|
||||
|
||||
test('unpaired-surrogate', () {
|
||||
// (0xD834, 0xDD1E) = 0x1D11E
|
||||
// Strings containing unpaired surrogates must be encoded to prevent
|
||||
// problems with the utf8 file-level encoding.
|
||||
check([0xD834], [$DQ, 0xD834, $DQ]); // Legacy escapedString broken.
|
||||
check([0xD834], [$DQ, $BACKSLASH, $u, $d, $8, $3, $4, $DQ], ascii: true);
|
||||
check([0xD834], [$DQ, $BACKSLASH, $u, $d, $8, $3, $4, $DQ], utf8: true);
|
||||
// (0xD834, 0xDD1E) = 0x1D11E
|
||||
// Strings containing unpaired surrogates must be encoded to prevent
|
||||
// problems with the utf8 file-level encoding.
|
||||
check([0xD834], [$DQ, 0xD834, $DQ]); // Legacy escapedString broken.
|
||||
check([0xD834], [$DQ, $BACKSLASH, $u, $d, $8, $3, $4, $DQ], ascii: true);
|
||||
check([0xD834], [$DQ, $BACKSLASH, $u, $d, $8, $3, $4, $DQ], utf8: true);
|
||||
|
||||
check([0xDD1E], [$DQ, 0xDD1E, $DQ]); // Legacy escapedString broken.
|
||||
check([0xDD1E], [$DQ, $BACKSLASH, $u, $d, $d, $1, $e, $DQ], ascii: true);
|
||||
check([0xDD1E], [$DQ, $BACKSLASH, $u, $d, $d, $1, $e, $DQ], utf8: true);
|
||||
check([0xDD1E], [$DQ, 0xDD1E, $DQ]); // Legacy escapedString broken.
|
||||
check([0xDD1E], [$DQ, $BACKSLASH, $u, $d, $d, $1, $e, $DQ], ascii: true);
|
||||
check([0xDD1E], [$DQ, $BACKSLASH, $u, $d, $d, $1, $e, $DQ], utf8: true);
|
||||
|
||||
check([0xD834, $A],
|
||||
[$DQ, 0xD834, $A, $DQ]); // Legacy escapedString broken.
|
||||
check([0xD834, $A],
|
||||
[$DQ, $BACKSLASH, $u, $d, $8, $3, $4, $A, $DQ],
|
||||
ascii: true);
|
||||
check([0xD834, $A],
|
||||
[$DQ, $BACKSLASH, $u, $d, $8, $3, $4, $A, $DQ],
|
||||
utf8: true);
|
||||
check([0xD834, $A], [$DQ, 0xD834, $A, $DQ]); // Legacy escapedString broken.
|
||||
check([0xD834, $A], [$DQ, $BACKSLASH, $u, $d, $8, $3, $4, $A, $DQ],
|
||||
ascii: true);
|
||||
check([0xD834, $A], [$DQ, $BACKSLASH, $u, $d, $8, $3, $4, $A, $DQ],
|
||||
utf8: true);
|
||||
|
||||
check([0xD834, 0xDD1E], [$DQ, 0xD834, 0xDD1E, $DQ]); // Legacy ok.
|
||||
check([0xD834, 0xDD1E],
|
||||
[$DQ,
|
||||
$BACKSLASH, $u, $d, $8, $3, $4,
|
||||
$BACKSLASH, $u, $d, $d, $1, $e,
|
||||
$DQ],
|
||||
ascii: true);
|
||||
check([0xD834, 0xDD1E], r'''"\ud834\udd1e"''', ascii: true);
|
||||
check([0xD834, 0xDD1E], [$DQ, 0xD834, 0xDD1E, $DQ], utf8: true);
|
||||
});
|
||||
check([0xD834, 0xDD1E], [$DQ, 0xD834, 0xDD1E, $DQ]); // Legacy ok.
|
||||
check([
|
||||
0xD834,
|
||||
0xDD1E
|
||||
], [
|
||||
$DQ,
|
||||
$BACKSLASH,
|
||||
$u,
|
||||
$d,
|
||||
$8,
|
||||
$3,
|
||||
$4,
|
||||
$BACKSLASH,
|
||||
$u,
|
||||
$d,
|
||||
$d,
|
||||
$1,
|
||||
$e,
|
||||
$DQ
|
||||
], ascii: true);
|
||||
check([0xD834, 0xDD1E], r'''"\ud834\udd1e"''', ascii: true);
|
||||
check([0xD834, 0xDD1E], [$DQ, 0xD834, 0xDD1E, $DQ], utf8: true);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue