Merge branch '2' into 2-docs

This commit is contained in:
Geoffrey Booth
2017-01-12 21:57:16 -08:00
16 changed files with 5651 additions and 3816 deletions

View File

@@ -7,10 +7,8 @@
ref1 = require('./helpers'), count = ref1.count, starts = ref1.starts, compact = ref1.compact, repeat = ref1.repeat, invertLiterate = ref1.invertLiterate, locationDataToString = ref1.locationDataToString, throwSyntaxError = ref1.throwSyntaxError;
exports.Lexer = Lexer = (function() {
function Lexer() {}
Lexer.prototype.tokenize = function(code, opts = {}) {
exports.Lexer = Lexer = class Lexer {
tokenize(code, opts = {}) {
var consumed, end, i, ref2;
this.literate = opts.literate;
this.indent = 0;
@@ -48,9 +46,9 @@
return this.tokens;
}
return (new Rewriter).rewrite(this.tokens);
};
}
Lexer.prototype.clean = function(code) {
clean(code) {
if (code.charCodeAt(0) === BOM) {
code = code.slice(1);
}
@@ -63,9 +61,9 @@
code = invertLiterate(code);
}
return code;
};
}
Lexer.prototype.identifierToken = function() {
identifierToken() {
var alias, colon, colonOffset, id, idLength, input, match, poppedToken, prev, ref2, ref3, ref4, ref5, ref6, ref7, tag, tagToken;
if (!(match = IDENTIFIER.exec(this.chunk))) {
return 0;
@@ -176,9 +174,9 @@
this.token(':', ':', colonOffset, colon.length);
}
return input.length;
};
}
Lexer.prototype.numberToken = function() {
numberToken() {
var base, lexedLength, match, number, numberValue, tag;
if (!(match = NUMBER.exec(this.chunk))) {
return 0;
@@ -222,9 +220,9 @@
tag = numberValue === 2e308 ? 'INFINITY' : 'NUMBER';
this.token(tag, number, 0, lexedLength);
return lexedLength;
};
}
Lexer.prototype.stringToken = function() {
stringToken() {
var $, attempt, delimiter, doc, end, heredoc, i, indent, indentRegex, match, quote, ref2, ref3, regex, token, tokens;
quote = (STRING_START.exec(this.chunk) || [])[0];
if (!quote) {
@@ -302,9 +300,9 @@
});
}
return end;
};
}
Lexer.prototype.commentToken = function() {
commentToken() {
var comment, here, match;
if (!(match = this.chunk.match(COMMENT))) {
return 0;
@@ -323,9 +321,9 @@
this.token('HERECOMMENT', here, 0, comment.length);
}
return comment.length;
};
}
Lexer.prototype.jsToken = function() {
jsToken() {
var match, script;
if (!(this.chunk.charAt(0) === '`' && (match = HERE_JSTOKEN.exec(this.chunk) || JSTOKEN.exec(this.chunk)))) {
return 0;
@@ -335,9 +333,9 @@
});
this.token('JS', script, 0, match[0].length);
return match[0].length;
};
}
Lexer.prototype.regexToken = function() {
regexToken() {
var body, closed, end, flags, index, match, origin, prev, ref2, ref3, ref4, regex, tokens;
switch (false) {
case !(match = REGEX_ILLEGAL.exec(this.chunk)):
@@ -406,9 +404,9 @@
this.token('REGEX_END', ')', end, 0);
}
return end;
};
}
Lexer.prototype.lineToken = function() {
lineToken() {
var diff, indent, match, minLiteralLength, newIndentLiteral, noNewlines, size;
if (!(match = MULTI_DENT.exec(this.chunk))) {
return 0;
@@ -468,9 +466,9 @@
this.outdentToken(this.indent - size, noNewlines, indent.length);
}
return indent.length;
};
}
Lexer.prototype.outdentToken = function(moveOut, noNewlines, outdentLength) {
outdentToken(moveOut, noNewlines, outdentLength) {
var decreasedIndent, dent, lastIndent, ref2;
decreasedIndent = this.indent - moveOut;
while (moveOut > 0) {
@@ -507,9 +505,9 @@
this.indent = decreasedIndent;
this.indentLiteral = this.indentLiteral.slice(0, decreasedIndent);
return this;
};
}
Lexer.prototype.whitespaceToken = function() {
whitespaceToken() {
var match, nline, prev, ref2;
if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) {
return 0;
@@ -523,9 +521,9 @@
} else {
return 0;
}
};
}
Lexer.prototype.newlineToken = function(offset) {
newlineToken(offset) {
while (this.value() === ';') {
this.tokens.pop();
}
@@ -533,16 +531,16 @@
this.token('TERMINATOR', '\n', offset, 0);
}
return this;
};
}
Lexer.prototype.suppressNewlines = function() {
suppressNewlines() {
if (this.value() === '\\') {
this.tokens.pop();
}
return this;
};
}
Lexer.prototype.literalToken = function() {
literalToken() {
var match, message, origin, prev, ref2, ref3, ref4, ref5, ref6, skipToken, tag, token, value;
if (match = OPERATOR.exec(this.chunk)) {
value = match[0];
@@ -628,9 +626,9 @@
}
this.tokens.push(token);
return value.length;
};
}
Lexer.prototype.tagParameters = function() {
tagParameters() {
var i, stack, tok, tokens;
if (this.tag() !== ')') {
return this;
@@ -657,13 +655,13 @@
}
}
return this;
};
}
Lexer.prototype.closeIndentation = function() {
closeIndentation() {
return this.outdentToken(this.indent);
};
}
Lexer.prototype.matchWithInterpolations = function(regex, delimiter) {
matchWithInterpolations(regex, delimiter) {
var close, column, firstToken, index, lastToken, line, nested, offsetInChunk, open, ref2, ref3, ref4, str, strPart, tokens;
tokens = [];
offsetInChunk = delimiter.length;
@@ -721,9 +719,9 @@
tokens: tokens,
index: offsetInChunk + delimiter.length
};
};
}
Lexer.prototype.mergeInterpolationTokens = function(tokens, options, fn) {
mergeInterpolationTokens(tokens, options, fn) {
var converted, firstEmptyStringIndex, firstIndex, i, j, lastToken, len, locationToken, lparen, plusToken, rparen, tag, token, tokensToPush, value;
if (tokens.length > 1) {
lparen = this.token('STRING_START', '(', 0, 0);
@@ -786,9 +784,9 @@
last_column: lastToken[2].last_column
};
}
};
}
Lexer.prototype.pair = function(tag) {
pair(tag) {
var lastIndent, prev, ref2, ref3, wanted;
ref2 = this.ends, prev = ref2[ref2.length - 1];
if (tag !== (wanted = prev != null ? prev.tag : void 0)) {
@@ -800,9 +798,9 @@
return this.pair(tag);
}
return this.ends.pop();
};
}
Lexer.prototype.getLineAndColumnFromChunk = function(offset) {
getLineAndColumnFromChunk(offset) {
var column, lastLine, lineCount, ref2, string;
if (offset === 0) {
return [this.chunkLine, this.chunkColumn];
@@ -821,9 +819,9 @@
column += string.length;
}
return [this.chunkLine + lineCount, column];
};
}
Lexer.prototype.makeToken = function(tag, value, offsetInChunk = 0, length = value.length) {
makeToken(tag, value, offsetInChunk = 0, length = value.length) {
var lastCharacter, locationData, ref2, ref3, token;
locationData = {};
ref2 = this.getLineAndColumnFromChunk(offsetInChunk), locationData.first_line = ref2[0], locationData.first_column = ref2[1];
@@ -831,9 +829,9 @@
ref3 = this.getLineAndColumnFromChunk(offsetInChunk + lastCharacter), locationData.last_line = ref3[0], locationData.last_column = ref3[1];
token = [tag, value, locationData];
return token;
};
}
Lexer.prototype.token = function(tag, value, offsetInChunk, length, origin) {
token(tag, value, offsetInChunk, length, origin) {
var token;
token = this.makeToken(tag, value, offsetInChunk, length);
if (origin) {
@@ -841,34 +839,34 @@
}
this.tokens.push(token);
return token;
};
}
Lexer.prototype.tag = function() {
tag() {
var ref2, token;
ref2 = this.tokens, token = ref2[ref2.length - 1];
return token != null ? token[0] : void 0;
};
}
Lexer.prototype.value = function() {
value() {
var ref2, token;
ref2 = this.tokens, token = ref2[ref2.length - 1];
return token != null ? token[1] : void 0;
};
}
Lexer.prototype.unfinished = function() {
unfinished() {
var ref2;
return LINE_CONTINUER.test(this.chunk) || ((ref2 = this.tag()) === '\\' || ref2 === '.' || ref2 === '?.' || ref2 === '?::' || ref2 === 'UNARY' || ref2 === 'MATH' || ref2 === 'UNARY_MATH' || ref2 === '+' || ref2 === '-' || ref2 === '**' || ref2 === 'SHIFT' || ref2 === 'RELATION' || ref2 === 'COMPARE' || ref2 === '&' || ref2 === '^' || ref2 === '|' || ref2 === '&&' || ref2 === '||' || ref2 === 'BIN?' || ref2 === 'THROW' || ref2 === 'EXTENDS');
};
}
Lexer.prototype.formatString = function(str) {
formatString(str) {
return str.replace(STRING_OMIT, '$1');
};
}
Lexer.prototype.formatHeregex = function(str) {
formatHeregex(str) {
return str.replace(HEREGEX_OMIT, '$1$2');
};
}
Lexer.prototype.validateEscapes = function(str, options = {}) {
validateEscapes(str, options = {}) {
var before, hex, invalidEscape, match, message, octal, ref2, unicode;
match = INVALID_ESCAPE.exec(str);
if (!match) {
@@ -884,9 +882,9 @@
offset: ((ref2 = options.offsetInChunk) != null ? ref2 : 0) + match.index + before.length,
length: invalidEscape.length
});
};
}
Lexer.prototype.makeDelimitedLiteral = function(body, options = {}) {
makeDelimitedLiteral(body, options = {}) {
var regex;
if (body === '' && options.delimiter === '/') {
body = '(?:)';
@@ -921,9 +919,9 @@
}
});
return `${options.delimiter}${body}${options.delimiter}`;
};
}
Lexer.prototype.error = function(message, options = {}) {
error(message, options = {}) {
var first_column, first_line, location, ref2, ref3, ref4;
location = 'first_line' in options ? options : ((ref3 = this.getLineAndColumnFromChunk((ref2 = options.offset) != null ? ref2 : 0), first_line = ref3[0], first_column = ref3[1], ref3), {
first_line: first_line,
@@ -931,11 +929,9 @@
last_column: first_column + ((ref4 = options.length) != null ? ref4 : 1) - 1
});
return throwSyntaxError(message, location);
};
}
return Lexer;
})();
};
isUnassignable = function(name, displayName = name) {
switch (false) {

File diff suppressed because it is too large Load Diff

View File

@@ -4,13 +4,13 @@
repeat = require('./helpers').repeat;
exports.OptionParser = OptionParser = (function() {
function OptionParser(rules, banner) {
exports.OptionParser = OptionParser = class OptionParser {
constructor(rules, banner) {
this.banner = banner;
this.rules = buildRules(rules);
}
OptionParser.prototype.parse = function(args) {
parse(args) {
var arg, i, isOption, j, k, len, len1, matchedRule, options, originalArgs, pos, ref, rule, seenNonOptionArg, skippingArgument, value;
options = {
"arguments": []
@@ -56,9 +56,9 @@
}
}
return options;
};
}
OptionParser.prototype.help = function() {
help() {
var j, len, letPart, lines, ref, rule, spaces;
lines = [];
if (this.banner) {
@@ -73,11 +73,9 @@
lines.push(' ' + letPart + rule.longFlag + spaces + rule.description);
}
return `\n${lines.join('\n')}\n`;
};
}
return OptionParser;
})();
};
LONG_FLAG = /^(--\w[\w\-]*)/;

View File

@@ -14,470 +14,471 @@
};
exports.Rewriter = (function() {
function Rewriter() {}
Rewriter.prototype.rewrite = function(tokens1) {
this.tokens = tokens1;
this.removeLeadingNewlines();
this.closeOpenCalls();
this.closeOpenIndexes();
this.normalizeLines();
this.tagPostfixConditionals();
this.addImplicitBracesAndParens();
this.addLocationDataToGeneratedTokens();
this.fixOutdentLocationData();
return this.tokens;
};
Rewriter.prototype.scanTokens = function(block) {
var i, token, tokens;
tokens = this.tokens;
i = 0;
while (token = tokens[i]) {
i += block.call(this, token, i, tokens);
class Rewriter {
rewrite(tokens1) {
this.tokens = tokens1;
this.removeLeadingNewlines();
this.closeOpenCalls();
this.closeOpenIndexes();
this.normalizeLines();
this.tagPostfixConditionals();
this.addImplicitBracesAndParens();
this.addLocationDataToGeneratedTokens();
this.fixOutdentLocationData();
return this.tokens;
}
return true;
};
Rewriter.prototype.detectEnd = function(i, condition, action) {
var levels, ref, ref1, token, tokens;
tokens = this.tokens;
levels = 0;
while (token = tokens[i]) {
if (levels === 0 && condition.call(this, token, i)) {
return action.call(this, token, i);
scanTokens(block) {
var i, token, tokens;
tokens = this.tokens;
i = 0;
while (token = tokens[i]) {
i += block.call(this, token, i, tokens);
}
if (!token || levels < 0) {
return action.call(this, token, i - 1);
}
if (ref = token[0], indexOf.call(EXPRESSION_START, ref) >= 0) {
levels += 1;
} else if (ref1 = token[0], indexOf.call(EXPRESSION_END, ref1) >= 0) {
levels -= 1;
}
i += 1;
}
return i - 1;
};
Rewriter.prototype.removeLeadingNewlines = function() {
var i, k, len, ref, tag;
ref = this.tokens;
for (i = k = 0, len = ref.length; k < len; i = ++k) {
tag = ref[i][0];
if (tag !== 'TERMINATOR') {
break;
}
}
if (i) {
return this.tokens.splice(0, i);
}
};
Rewriter.prototype.closeOpenCalls = function() {
var action, condition;
condition = function(token, i) {
var ref;
return ((ref = token[0]) === ')' || ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')';
};
action = function(token, i) {
return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
};
return this.scanTokens(function(token, i) {
if (token[0] === 'CALL_START') {
this.detectEnd(i + 1, condition, action);
}
return 1;
});
};
Rewriter.prototype.closeOpenIndexes = function() {
var action, condition;
condition = function(token, i) {
var ref;
return (ref = token[0]) === ']' || ref === 'INDEX_END';
};
action = function(token, i) {
return token[0] = 'INDEX_END';
};
return this.scanTokens(function(token, i) {
if (token[0] === 'INDEX_START') {
this.detectEnd(i + 1, condition, action);
}
return 1;
});
};
Rewriter.prototype.indexOfTag = function(i, ...pattern) {
var fuzz, j, k, ref, ref1;
fuzz = 0;
for (j = k = 0, ref = pattern.length; 0 <= ref ? k < ref : k > ref; j = 0 <= ref ? ++k : --k) {
while (this.tag(i + j + fuzz) === 'HERECOMMENT') {
fuzz += 2;
}
if (pattern[j] == null) {
continue;
}
if (typeof pattern[j] === 'string') {
pattern[j] = [pattern[j]];
}
if (ref1 = this.tag(i + j + fuzz), indexOf.call(pattern[j], ref1) < 0) {
return -1;
}
}
return i + j + fuzz - 1;
};
Rewriter.prototype.looksObjectish = function(j) {
var end, index;
if (this.indexOfTag(j, '@', null, ':') > -1 || this.indexOfTag(j, null, ':') > -1) {
return true;
}
index = this.indexOfTag(j, EXPRESSION_START);
if (index > -1) {
end = null;
this.detectEnd(index + 1, (function(token) {
detectEnd(i, condition, action) {
var levels, ref, ref1, token, tokens;
tokens = this.tokens;
levels = 0;
while (token = tokens[i]) {
if (levels === 0 && condition.call(this, token, i)) {
return action.call(this, token, i);
}
if (!token || levels < 0) {
return action.call(this, token, i - 1);
}
if (ref = token[0], indexOf.call(EXPRESSION_START, ref) >= 0) {
levels += 1;
} else if (ref1 = token[0], indexOf.call(EXPRESSION_END, ref1) >= 0) {
levels -= 1;
}
i += 1;
}
return i - 1;
}
removeLeadingNewlines() {
var i, k, len, ref, tag;
ref = this.tokens;
for (i = k = 0, len = ref.length; k < len; i = ++k) {
tag = ref[i][0];
if (tag !== 'TERMINATOR') {
break;
}
}
if (i) {
return this.tokens.splice(0, i);
}
}
closeOpenCalls() {
var action, condition;
condition = function(token, i) {
var ref;
return ref = token[0], indexOf.call(EXPRESSION_END, ref) >= 0;
}), (function(token, i) {
return end = i;
}));
if (this.tag(end + 1) === ':') {
return ((ref = token[0]) === ')' || ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')';
};
action = function(token, i) {
return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
};
return this.scanTokens(function(token, i) {
if (token[0] === 'CALL_START') {
this.detectEnd(i + 1, condition, action);
}
return 1;
});
}
closeOpenIndexes() {
var action, condition;
condition = function(token, i) {
var ref;
return (ref = token[0]) === ']' || ref === 'INDEX_END';
};
action = function(token, i) {
return token[0] = 'INDEX_END';
};
return this.scanTokens(function(token, i) {
if (token[0] === 'INDEX_START') {
this.detectEnd(i + 1, condition, action);
}
return 1;
});
}
indexOfTag(i, ...pattern) {
var fuzz, j, k, ref, ref1;
fuzz = 0;
for (j = k = 0, ref = pattern.length; 0 <= ref ? k < ref : k > ref; j = 0 <= ref ? ++k : --k) {
while (this.tag(i + j + fuzz) === 'HERECOMMENT') {
fuzz += 2;
}
if (pattern[j] == null) {
continue;
}
if (typeof pattern[j] === 'string') {
pattern[j] = [pattern[j]];
}
if (ref1 = this.tag(i + j + fuzz), indexOf.call(pattern[j], ref1) < 0) {
return -1;
}
}
return i + j + fuzz - 1;
}
looksObjectish(j) {
var end, index;
if (this.indexOfTag(j, '@', null, ':') > -1 || this.indexOfTag(j, null, ':') > -1) {
return true;
}
index = this.indexOfTag(j, EXPRESSION_START);
if (index > -1) {
end = null;
this.detectEnd(index + 1, (function(token) {
var ref;
return ref = token[0], indexOf.call(EXPRESSION_END, ref) >= 0;
}), (function(token, i) {
return end = i;
}));
if (this.tag(end + 1) === ':') {
return true;
}
}
return false;
}
return false;
};
Rewriter.prototype.findTagsBackwards = function(i, tags) {
var backStack, ref, ref1, ref2, ref3, ref4, ref5;
backStack = [];
while (i >= 0 && (backStack.length || (ref2 = this.tag(i), indexOf.call(tags, ref2) < 0) && ((ref3 = this.tag(i), indexOf.call(EXPRESSION_START, ref3) < 0) || this.tokens[i].generated) && (ref4 = this.tag(i), indexOf.call(LINEBREAKS, ref4) < 0))) {
if (ref = this.tag(i), indexOf.call(EXPRESSION_END, ref) >= 0) {
backStack.push(this.tag(i));
findTagsBackwards(i, tags) {
var backStack, ref, ref1, ref2, ref3, ref4, ref5;
backStack = [];
while (i >= 0 && (backStack.length || (ref2 = this.tag(i), indexOf.call(tags, ref2) < 0) && ((ref3 = this.tag(i), indexOf.call(EXPRESSION_START, ref3) < 0) || this.tokens[i].generated) && (ref4 = this.tag(i), indexOf.call(LINEBREAKS, ref4) < 0))) {
if (ref = this.tag(i), indexOf.call(EXPRESSION_END, ref) >= 0) {
backStack.push(this.tag(i));
}
if ((ref1 = this.tag(i), indexOf.call(EXPRESSION_START, ref1) >= 0) && backStack.length) {
backStack.pop();
}
i -= 1;
}
if ((ref1 = this.tag(i), indexOf.call(EXPRESSION_START, ref1) >= 0) && backStack.length) {
backStack.pop();
}
i -= 1;
return ref5 = this.tag(i), indexOf.call(tags, ref5) >= 0;
}
return ref5 = this.tag(i), indexOf.call(tags, ref5) >= 0;
};
Rewriter.prototype.addImplicitBracesAndParens = function() {
var stack, start;
stack = [];
start = null;
return this.scanTokens(function(token, i, tokens) {
var endImplicitCall, endImplicitObject, forward, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, newLine, nextTag, offset, prevTag, prevToken, ref, ref1, ref2, ref3, ref4, ref5, s, sameLine, stackIdx, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
tag = token[0];
prevTag = (prevToken = i > 0 ? tokens[i - 1] : [])[0];
nextTag = (i < tokens.length - 1 ? tokens[i + 1] : [])[0];
stackTop = function() {
return stack[stack.length - 1];
};
startIdx = i;
forward = function(n) {
return i - startIdx + n;
};
inImplicit = function() {
var ref, ref1;
return (ref = stackTop()) != null ? (ref1 = ref[2]) != null ? ref1.ours : void 0 : void 0;
};
inImplicitCall = function() {
var ref;
return inImplicit() && ((ref = stackTop()) != null ? ref[0] : void 0) === '(';
};
inImplicitObject = function() {
var ref;
return inImplicit() && ((ref = stackTop()) != null ? ref[0] : void 0) === '{';
};
inImplicitControl = function() {
var ref;
return inImplicit && ((ref = stackTop()) != null ? ref[0] : void 0) === 'CONTROL';
};
startImplicitCall = function(j) {
var idx;
idx = j != null ? j : i;
stack.push([
'(', idx, {
ours: true
addImplicitBracesAndParens() {
var stack, start;
stack = [];
start = null;
return this.scanTokens(function(token, i, tokens) {
var endImplicitCall, endImplicitObject, forward, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, newLine, nextTag, offset, prevTag, prevToken, ref, ref1, ref2, ref3, ref4, ref5, s, sameLine, stackIdx, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
tag = token[0];
prevTag = (prevToken = i > 0 ? tokens[i - 1] : [])[0];
nextTag = (i < tokens.length - 1 ? tokens[i + 1] : [])[0];
stackTop = function() {
return stack[stack.length - 1];
};
startIdx = i;
forward = function(n) {
return i - startIdx + n;
};
inImplicit = function() {
var ref, ref1;
return (ref = stackTop()) != null ? (ref1 = ref[2]) != null ? ref1.ours : void 0 : void 0;
};
inImplicitCall = function() {
var ref;
return inImplicit() && ((ref = stackTop()) != null ? ref[0] : void 0) === '(';
};
inImplicitObject = function() {
var ref;
return inImplicit() && ((ref = stackTop()) != null ? ref[0] : void 0) === '{';
};
inImplicitControl = function() {
var ref;
return inImplicit && ((ref = stackTop()) != null ? ref[0] : void 0) === 'CONTROL';
};
startImplicitCall = function(j) {
var idx;
idx = j != null ? j : i;
stack.push([
'(', idx, {
ours: true
}
]);
tokens.splice(idx, 0, generate('CALL_START', '('));
if (j == null) {
return i += 1;
}
]);
tokens.splice(idx, 0, generate('CALL_START', '('));
if (j == null) {
return i += 1;
}
};
endImplicitCall = function() {
stack.pop();
tokens.splice(i, 0, generate('CALL_END', ')', ['', 'end of input', token[2]]));
return i += 1;
};
startImplicitObject = function(j, startsLine = true) {
var idx, val;
idx = j != null ? j : i;
stack.push([
'{', idx, {
sameLine: true,
startsLine: startsLine,
ours: true
}
]);
val = new String('{');
val.generated = true;
tokens.splice(idx, 0, generate('{', val, token));
if (j == null) {
return i += 1;
}
};
endImplicitObject = function(j) {
j = j != null ? j : i;
stack.pop();
tokens.splice(j, 0, generate('}', '}', token));
return i += 1;
};
if (inImplicitCall() && (tag === 'IF' || tag === 'TRY' || tag === 'FINALLY' || tag === 'CATCH' || tag === 'CLASS' || tag === 'SWITCH')) {
stack.push([
'CONTROL', i, {
ours: true
}
]);
return forward(1);
}
if (tag === 'INDENT' && inImplicit()) {
if (prevTag !== '=>' && prevTag !== '->' && prevTag !== '[' && prevTag !== '(' && prevTag !== ',' && prevTag !== '{' && prevTag !== 'TRY' && prevTag !== 'ELSE' && prevTag !== '=') {
while (inImplicitCall()) {
endImplicitCall();
}
}
if (inImplicitControl()) {
};
endImplicitCall = function() {
stack.pop();
tokens.splice(i, 0, generate('CALL_END', ')', ['', 'end of input', token[2]]));
return i += 1;
};
startImplicitObject = function(j, startsLine = true) {
var idx, val;
idx = j != null ? j : i;
stack.push([
'{', idx, {
sameLine: true,
startsLine: startsLine,
ours: true
}
]);
val = new String('{');
val.generated = true;
tokens.splice(idx, 0, generate('{', val, token));
if (j == null) {
return i += 1;
}
};
endImplicitObject = function(j) {
j = j != null ? j : i;
stack.pop();
tokens.splice(j, 0, generate('}', '}', token));
return i += 1;
};
if (inImplicitCall() && (tag === 'IF' || tag === 'TRY' || tag === 'FINALLY' || tag === 'CATCH' || tag === 'CLASS' || tag === 'SWITCH')) {
stack.push([
'CONTROL', i, {
ours: true
}
]);
return forward(1);
}
stack.push([tag, i]);
return forward(1);
}
if (indexOf.call(EXPRESSION_START, tag) >= 0) {
stack.push([tag, i]);
return forward(1);
}
if (indexOf.call(EXPRESSION_END, tag) >= 0) {
while (inImplicit()) {
if (inImplicitCall()) {
endImplicitCall();
} else if (inImplicitObject()) {
endImplicitObject();
} else {
if (tag === 'INDENT' && inImplicit()) {
if (prevTag !== '=>' && prevTag !== '->' && prevTag !== '[' && prevTag !== '(' && prevTag !== ',' && prevTag !== '{' && prevTag !== 'TRY' && prevTag !== 'ELSE' && prevTag !== '=') {
while (inImplicitCall()) {
endImplicitCall();
}
}
if (inImplicitControl()) {
stack.pop();
}
stack.push([tag, i]);
return forward(1);
}
start = stack.pop();
}
if ((indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !((ref = tokens[i + 1]) != null ? ref.spaced : void 0) && !((ref1 = tokens[i + 1]) != null ? ref1.newLine : void 0))) {
if (tag === '?') {
tag = token[0] = 'FUNC_EXIST';
if (indexOf.call(EXPRESSION_START, tag) >= 0) {
stack.push([tag, i]);
return forward(1);
}
startImplicitCall(i + 1);
return forward(2);
}
if (indexOf.call(IMPLICIT_FUNC, tag) >= 0 && this.indexOfTag(i + 1, 'INDENT') > -1 && this.looksObjectish(i + 2) && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])) {
startImplicitCall(i + 1);
stack.push(['INDENT', i + 2]);
return forward(3);
}
if (tag === ':') {
s = (function() {
var ref2;
switch (false) {
case ref2 = this.tag(i - 1), indexOf.call(EXPRESSION_END, ref2) < 0:
return start[1];
case this.tag(i - 2) !== '@':
return i - 2;
default:
return i - 1;
if (indexOf.call(EXPRESSION_END, tag) >= 0) {
while (inImplicit()) {
if (inImplicitCall()) {
endImplicitCall();
} else if (inImplicitObject()) {
endImplicitObject();
} else {
stack.pop();
}
}
}).call(this);
while (this.tag(s - 2) === 'HERECOMMENT') {
s -= 2;
start = stack.pop();
}
this.insideForDeclaration = nextTag === 'FOR';
startsLine = s === 0 || (ref2 = this.tag(s - 1), indexOf.call(LINEBREAKS, ref2) >= 0) || tokens[s - 1].newLine;
if (stackTop()) {
ref3 = stackTop(), stackTag = ref3[0], stackIdx = ref3[1];
if ((stackTag === '{' || stackTag === 'INDENT' && this.tag(stackIdx - 1) === '{') && (startsLine || this.tag(s - 1) === ',' || this.tag(s - 1) === '{')) {
return forward(1);
if ((indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !((ref = tokens[i + 1]) != null ? ref.spaced : void 0) && !((ref1 = tokens[i + 1]) != null ? ref1.newLine : void 0))) {
if (tag === '?') {
tag = token[0] = 'FUNC_EXIST';
}
startImplicitCall(i + 1);
return forward(2);
}
startImplicitObject(s, !!startsLine);
return forward(2);
}
if (inImplicitObject() && indexOf.call(LINEBREAKS, tag) >= 0) {
stackTop()[2].sameLine = false;
}
newLine = prevTag === 'OUTDENT' || prevToken.newLine;
if (indexOf.call(IMPLICIT_END, tag) >= 0 || indexOf.call(CALL_CLOSERS, tag) >= 0 && newLine) {
while (inImplicit()) {
ref4 = stackTop(), stackTag = ref4[0], stackIdx = ref4[1], (ref5 = ref4[2], sameLine = ref5.sameLine, startsLine = ref5.startsLine);
if (inImplicitCall() && prevTag !== ',') {
endImplicitCall();
} else if (inImplicitObject() && !this.insideForDeclaration && sameLine && tag !== 'TERMINATOR' && prevTag !== ':') {
endImplicitObject();
} else if (inImplicitObject() && tag === 'TERMINATOR' && prevTag !== ',' && !(startsLine && this.looksObjectish(i + 1))) {
if (nextTag === 'HERECOMMENT') {
if (indexOf.call(IMPLICIT_FUNC, tag) >= 0 && this.indexOfTag(i + 1, 'INDENT') > -1 && this.looksObjectish(i + 2) && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])) {
startImplicitCall(i + 1);
stack.push(['INDENT', i + 2]);
return forward(3);
}
if (tag === ':') {
s = (function() {
var ref2;
switch (false) {
case ref2 = this.tag(i - 1), indexOf.call(EXPRESSION_END, ref2) < 0:
return start[1];
case this.tag(i - 2) !== '@':
return i - 2;
default:
return i - 1;
}
}).call(this);
while (this.tag(s - 2) === 'HERECOMMENT') {
s -= 2;
}
this.insideForDeclaration = nextTag === 'FOR';
startsLine = s === 0 || (ref2 = this.tag(s - 1), indexOf.call(LINEBREAKS, ref2) >= 0) || tokens[s - 1].newLine;
if (stackTop()) {
ref3 = stackTop(), stackTag = ref3[0], stackIdx = ref3[1];
if ((stackTag === '{' || stackTag === 'INDENT' && this.tag(stackIdx - 1) === '{') && (startsLine || this.tag(s - 1) === ',' || this.tag(s - 1) === '{')) {
return forward(1);
}
endImplicitObject();
} else {
break;
}
startImplicitObject(s, !!startsLine);
return forward(2);
}
if (inImplicitObject() && indexOf.call(LINEBREAKS, tag) >= 0) {
stackTop()[2].sameLine = false;
}
newLine = prevTag === 'OUTDENT' || prevToken.newLine;
if (indexOf.call(IMPLICIT_END, tag) >= 0 || indexOf.call(CALL_CLOSERS, tag) >= 0 && newLine) {
while (inImplicit()) {
ref4 = stackTop(), stackTag = ref4[0], stackIdx = ref4[1], (ref5 = ref4[2], sameLine = ref5.sameLine, startsLine = ref5.startsLine);
if (inImplicitCall() && prevTag !== ',') {
endImplicitCall();
} else if (inImplicitObject() && !this.insideForDeclaration && sameLine && tag !== 'TERMINATOR' && prevTag !== ':') {
endImplicitObject();
} else if (inImplicitObject() && tag === 'TERMINATOR' && prevTag !== ',' && !(startsLine && this.looksObjectish(i + 1))) {
if (nextTag === 'HERECOMMENT') {
return forward(1);
}
endImplicitObject();
} else {
break;
}
}
}
}
if (tag === ',' && !this.looksObjectish(i + 1) && inImplicitObject() && !this.insideForDeclaration && (nextTag !== 'TERMINATOR' || !this.looksObjectish(i + 2))) {
offset = nextTag === 'OUTDENT' ? 1 : 0;
while (inImplicitObject()) {
endImplicitObject(i + offset);
if (tag === ',' && !this.looksObjectish(i + 1) && inImplicitObject() && !this.insideForDeclaration && (nextTag !== 'TERMINATOR' || !this.looksObjectish(i + 2))) {
offset = nextTag === 'OUTDENT' ? 1 : 0;
while (inImplicitObject()) {
endImplicitObject(i + offset);
}
}
}
return forward(1);
});
};
return forward(1);
});
}
Rewriter.prototype.addLocationDataToGeneratedTokens = function() {
return this.scanTokens(function(token, i, tokens) {
var column, line, nextLocation, prevLocation, ref, ref1;
if (token[2]) {
return 1;
}
if (!(token.generated || token.explicit)) {
return 1;
}
if (token[0] === '{' && (nextLocation = (ref = tokens[i + 1]) != null ? ref[2] : void 0)) {
line = nextLocation.first_line, column = nextLocation.first_column;
} else if (prevLocation = (ref1 = tokens[i - 1]) != null ? ref1[2] : void 0) {
line = prevLocation.last_line, column = prevLocation.last_column;
} else {
line = column = 0;
}
token[2] = {
first_line: line,
first_column: column,
last_line: line,
last_column: column
};
return 1;
});
};
Rewriter.prototype.fixOutdentLocationData = function() {
return this.scanTokens(function(token, i, tokens) {
var prevLocationData;
if (!(token[0] === 'OUTDENT' || (token.generated && token[0] === 'CALL_END') || (token.generated && token[0] === '}'))) {
return 1;
}
prevLocationData = tokens[i - 1][2];
token[2] = {
first_line: prevLocationData.last_line,
first_column: prevLocationData.last_column,
last_line: prevLocationData.last_line,
last_column: prevLocationData.last_column
};
return 1;
});
};
Rewriter.prototype.normalizeLines = function() {
var action, condition, indent, outdent, starter;
starter = indent = outdent = null;
condition = function(token, i) {
var ref, ref1, ref2, ref3;
return token[1] !== ';' && (ref = token[0], indexOf.call(SINGLE_CLOSERS, ref) >= 0) && !(token[0] === 'TERMINATOR' && (ref1 = this.tag(i + 1), indexOf.call(EXPRESSION_CLOSE, ref1) >= 0)) && !(token[0] === 'ELSE' && starter !== 'THEN') && !(((ref2 = token[0]) === 'CATCH' || ref2 === 'FINALLY') && (starter === '->' || starter === '=>')) || (ref3 = token[0], indexOf.call(CALL_CLOSERS, ref3) >= 0) && this.tokens[i - 1].newLine;
};
action = function(token, i) {
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
};
return this.scanTokens(function(token, i, tokens) {
var j, k, ref, ref1, ref2, tag;
tag = token[0];
if (tag === 'TERMINATOR') {
if (this.tag(i + 1) === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
tokens.splice(i, 1, ...this.indentation());
addLocationDataToGeneratedTokens() {
return this.scanTokens(function(token, i, tokens) {
var column, line, nextLocation, prevLocation, ref, ref1;
if (token[2]) {
return 1;
}
if (ref = this.tag(i + 1), indexOf.call(EXPRESSION_CLOSE, ref) >= 0) {
tokens.splice(i, 1);
return 0;
if (!(token.generated || token.explicit)) {
return 1;
}
}
if (tag === 'CATCH') {
for (j = k = 1; k <= 2; j = ++k) {
if (!((ref1 = this.tag(i + j)) === 'OUTDENT' || ref1 === 'TERMINATOR' || ref1 === 'FINALLY')) {
continue;
}
tokens.splice(i + j, 0, ...this.indentation());
return 2 + j;
}
}
if (indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
starter = tag;
ref2 = this.indentation(tokens[i]), indent = ref2[0], outdent = ref2[1];
if (starter === 'THEN') {
indent.fromThen = true;
}
tokens.splice(i + 1, 0, indent);
this.detectEnd(i + 2, condition, action);
if (tag === 'THEN') {
tokens.splice(i, 1);
if (token[0] === '{' && (nextLocation = (ref = tokens[i + 1]) != null ? ref[2] : void 0)) {
line = nextLocation.first_line, column = nextLocation.first_column;
} else if (prevLocation = (ref1 = tokens[i - 1]) != null ? ref1[2] : void 0) {
line = prevLocation.last_line, column = prevLocation.last_column;
} else {
line = column = 0;
}
token[2] = {
first_line: line,
first_column: column,
last_line: line,
last_column: column
};
return 1;
}
return 1;
});
};
Rewriter.prototype.tagPostfixConditionals = function() {
var action, condition, original;
original = null;
condition = function(token, i) {
var prevTag, tag;
tag = token[0];
prevTag = this.tokens[i - 1][0];
return tag === 'TERMINATOR' || (tag === 'INDENT' && indexOf.call(SINGLE_LINERS, prevTag) < 0);
};
action = function(token, i) {
if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) {
return original[0] = 'POST_' + original[0];
}
};
return this.scanTokens(function(token, i) {
if (token[0] !== 'IF') {
return 1;
}
original = token;
this.detectEnd(i + 1, condition, action);
return 1;
});
};
Rewriter.prototype.indentation = function(origin) {
var indent, outdent;
indent = ['INDENT', 2];
outdent = ['OUTDENT', 2];
if (origin) {
indent.generated = outdent.generated = true;
indent.origin = outdent.origin = origin;
} else {
indent.explicit = outdent.explicit = true;
});
}
return [indent, outdent];
fixOutdentLocationData() {
return this.scanTokens(function(token, i, tokens) {
var prevLocationData;
if (!(token[0] === 'OUTDENT' || (token.generated && token[0] === 'CALL_END') || (token.generated && token[0] === '}'))) {
return 1;
}
prevLocationData = tokens[i - 1][2];
token[2] = {
first_line: prevLocationData.last_line,
first_column: prevLocationData.last_column,
last_line: prevLocationData.last_line,
last_column: prevLocationData.last_column
};
return 1;
});
}
normalizeLines() {
var action, condition, indent, outdent, starter;
starter = indent = outdent = null;
condition = function(token, i) {
var ref, ref1, ref2, ref3;
return token[1] !== ';' && (ref = token[0], indexOf.call(SINGLE_CLOSERS, ref) >= 0) && !(token[0] === 'TERMINATOR' && (ref1 = this.tag(i + 1), indexOf.call(EXPRESSION_CLOSE, ref1) >= 0)) && !(token[0] === 'ELSE' && starter !== 'THEN') && !(((ref2 = token[0]) === 'CATCH' || ref2 === 'FINALLY') && (starter === '->' || starter === '=>')) || (ref3 = token[0], indexOf.call(CALL_CLOSERS, ref3) >= 0) && this.tokens[i - 1].newLine;
};
action = function(token, i) {
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
};
return this.scanTokens(function(token, i, tokens) {
var j, k, ref, ref1, ref2, tag;
tag = token[0];
if (tag === 'TERMINATOR') {
if (this.tag(i + 1) === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
tokens.splice(i, 1, ...this.indentation());
return 1;
}
if (ref = this.tag(i + 1), indexOf.call(EXPRESSION_CLOSE, ref) >= 0) {
tokens.splice(i, 1);
return 0;
}
}
if (tag === 'CATCH') {
for (j = k = 1; k <= 2; j = ++k) {
if (!((ref1 = this.tag(i + j)) === 'OUTDENT' || ref1 === 'TERMINATOR' || ref1 === 'FINALLY')) {
continue;
}
tokens.splice(i + j, 0, ...this.indentation());
return 2 + j;
}
}
if (indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
starter = tag;
ref2 = this.indentation(tokens[i]), indent = ref2[0], outdent = ref2[1];
if (starter === 'THEN') {
indent.fromThen = true;
}
tokens.splice(i + 1, 0, indent);
this.detectEnd(i + 2, condition, action);
if (tag === 'THEN') {
tokens.splice(i, 1);
}
return 1;
}
return 1;
});
}
tagPostfixConditionals() {
var action, condition, original;
original = null;
condition = function(token, i) {
var prevTag, tag;
tag = token[0];
prevTag = this.tokens[i - 1][0];
return tag === 'TERMINATOR' || (tag === 'INDENT' && indexOf.call(SINGLE_LINERS, prevTag) < 0);
};
action = function(token, i) {
if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) {
return original[0] = 'POST_' + original[0];
}
};
return this.scanTokens(function(token, i) {
if (token[0] !== 'IF') {
return 1;
}
original = token;
this.detectEnd(i + 1, condition, action);
return 1;
});
}
indentation(origin) {
var indent, outdent;
indent = ['INDENT', 2];
outdent = ['OUTDENT', 2];
if (origin) {
indent.generated = outdent.generated = true;
indent.origin = outdent.origin = origin;
} else {
indent.explicit = outdent.explicit = true;
}
return [indent, outdent];
}
tag(i) {
var ref;
return (ref = this.tokens[i]) != null ? ref[0] : void 0;
}
};
Rewriter.prototype.generate = generate;
Rewriter.prototype.tag = function(i) {
var ref;
return (ref = this.tokens[i]) != null ? ref[0] : void 0;
};
return Rewriter;
})();

View File

@@ -3,8 +3,8 @@
var Scope,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
exports.Scope = Scope = (function() {
function Scope(parent, expressions, method, referencedVars) {
exports.Scope = Scope = class Scope {
constructor(parent, expressions, method, referencedVars) {
var ref, ref1;
this.parent = parent;
this.expressions = expressions;
@@ -23,7 +23,7 @@
this.root = (ref = (ref1 = this.parent) != null ? ref1.root : void 0) != null ? ref : this;
}
Scope.prototype.add = function(name, type, immediate) {
add(name, type, immediate) {
if (this.shared && !immediate) {
return this.parent.add(name, type, immediate);
}
@@ -35,37 +35,37 @@
type: type
}) - 1;
}
};
}
Scope.prototype.namedMethod = function() {
namedMethod() {
var ref;
if (((ref = this.method) != null ? ref.name : void 0) || !this.parent) {
return this.method;
}
return this.parent.namedMethod();
};
}
Scope.prototype.find = function(name) {
find(name) {
if (this.check(name)) {
return true;
}
this.add(name, 'var');
return false;
};
}
Scope.prototype.parameter = function(name) {
parameter(name) {
if (this.shared && this.parent.check(name, true)) {
return;
}
return this.add(name, 'param');
};
}
Scope.prototype.check = function(name) {
check(name) {
var ref;
return !!(this.type(name) || ((ref = this.parent) != null ? ref.check(name) : void 0));
};
}
Scope.prototype.temporary = function(name, index, single = false) {
temporary(name, index, single = false) {
var diff, endCode, letter, newCode, num, startCode;
if (single) {
startCode = name.charCodeAt(0);
@@ -78,9 +78,9 @@
} else {
return `${name}${index || ''}`;
}
};
}
Scope.prototype.type = function(name) {
type(name) {
var i, len, ref, v;
ref = this.variables;
for (i = 0, len = ref.length; i < len; i++) {
@@ -90,9 +90,9 @@
}
}
return null;
};
}
Scope.prototype.freeVariable = function(name, options = {}) {
freeVariable(name, options = {}) {
var index, ref, temp;
index = 0;
while (true) {
@@ -106,21 +106,21 @@
this.add(temp, 'var', true);
}
return temp;
};
}
Scope.prototype.assign = function(name, value) {
assign(name, value) {
this.add(name, {
value: value,
assigned: true
}, true);
return this.hasAssignments = true;
};
}
Scope.prototype.hasDeclarations = function() {
hasDeclarations() {
return !!this.declaredVariables().length;
};
}
Scope.prototype.declaredVariables = function() {
declaredVariables() {
var v;
return ((function() {
var i, len, ref, results;
@@ -134,9 +134,9 @@
}
return results;
}).call(this)).sort();
};
}
Scope.prototype.assignedVariables = function() {
assignedVariables() {
var i, len, ref, results, v;
ref = this.variables;
results = [];
@@ -147,10 +147,8 @@
}
}
return results;
};
}
return Scope;
})();
};
}).call(this);

View File

@@ -2,13 +2,13 @@
(function() {
var LineMap, SourceMap;
LineMap = (function() {
function LineMap(line1) {
LineMap = class LineMap {
constructor(line1) {
this.line = line1;
this.columns = [];
}
LineMap.prototype.add = function(column, arg, options = {}) {
add(column, arg, options = {}) {
var sourceColumn, sourceLine;
sourceLine = arg[0], sourceColumn = arg[1];
if (this.columns[column] && options.noReplace) {
@@ -20,94 +20,117 @@
sourceLine: sourceLine,
sourceColumn: sourceColumn
};
};
}
LineMap.prototype.sourceLocation = function(column) {
sourceLocation(column) {
var mapping;
while (!((mapping = this.columns[column]) || (column <= 0))) {
column--;
}
return mapping && [mapping.sourceLine, mapping.sourceColumn];
};
}
return LineMap;
})();
};
SourceMap = (function() {
var BASE64_CHARS, VLQ_CONTINUATION_BIT, VLQ_SHIFT, VLQ_VALUE_MASK;
function SourceMap() {
this.lines = [];
}
SourceMap.prototype.add = function(sourceLocation, generatedLocation, options = {}) {
var base, column, line, lineMap;
line = generatedLocation[0], column = generatedLocation[1];
lineMap = ((base = this.lines)[line] || (base[line] = new LineMap(line)));
return lineMap.add(column, sourceLocation, options);
};
SourceMap.prototype.sourceLocation = function(arg) {
var column, line, lineMap;
line = arg[0], column = arg[1];
while (!((lineMap = this.lines[line]) || (line <= 0))) {
line--;
class SourceMap {
constructor() {
this.lines = [];
}
return lineMap && lineMap.sourceLocation(column);
};
SourceMap.prototype.generate = function(options = {}, code = null) {
var buffer, i, j, lastColumn, lastSourceColumn, lastSourceLine, len, len1, lineMap, lineNumber, mapping, needComma, ref, ref1, v3, writingline;
writingline = 0;
lastColumn = 0;
lastSourceLine = 0;
lastSourceColumn = 0;
needComma = false;
buffer = "";
ref = this.lines;
for (lineNumber = i = 0, len = ref.length; i < len; lineNumber = ++i) {
lineMap = ref[lineNumber];
if (lineMap) {
ref1 = lineMap.columns;
for (j = 0, len1 = ref1.length; j < len1; j++) {
mapping = ref1[j];
if (!(mapping)) {
continue;
add(sourceLocation, generatedLocation, options = {}) {
var base, column, line, lineMap;
line = generatedLocation[0], column = generatedLocation[1];
lineMap = ((base = this.lines)[line] || (base[line] = new LineMap(line)));
return lineMap.add(column, sourceLocation, options);
}
sourceLocation(arg) {
var column, line, lineMap;
line = arg[0], column = arg[1];
while (!((lineMap = this.lines[line]) || (line <= 0))) {
line--;
}
return lineMap && lineMap.sourceLocation(column);
}
generate(options = {}, code = null) {
var buffer, i, j, lastColumn, lastSourceColumn, lastSourceLine, len, len1, lineMap, lineNumber, mapping, needComma, ref, ref1, v3, writingline;
writingline = 0;
lastColumn = 0;
lastSourceLine = 0;
lastSourceColumn = 0;
needComma = false;
buffer = "";
ref = this.lines;
for (lineNumber = i = 0, len = ref.length; i < len; lineNumber = ++i) {
lineMap = ref[lineNumber];
if (lineMap) {
ref1 = lineMap.columns;
for (j = 0, len1 = ref1.length; j < len1; j++) {
mapping = ref1[j];
if (!(mapping)) {
continue;
}
while (writingline < mapping.line) {
lastColumn = 0;
needComma = false;
buffer += ";";
writingline++;
}
if (needComma) {
buffer += ",";
needComma = false;
}
buffer += this.encodeVlq(mapping.column - lastColumn);
lastColumn = mapping.column;
buffer += this.encodeVlq(0);
buffer += this.encodeVlq(mapping.sourceLine - lastSourceLine);
lastSourceLine = mapping.sourceLine;
buffer += this.encodeVlq(mapping.sourceColumn - lastSourceColumn);
lastSourceColumn = mapping.sourceColumn;
needComma = true;
}
while (writingline < mapping.line) {
lastColumn = 0;
needComma = false;
buffer += ";";
writingline++;
}
if (needComma) {
buffer += ",";
needComma = false;
}
buffer += this.encodeVlq(mapping.column - lastColumn);
lastColumn = mapping.column;
buffer += this.encodeVlq(0);
buffer += this.encodeVlq(mapping.sourceLine - lastSourceLine);
lastSourceLine = mapping.sourceLine;
buffer += this.encodeVlq(mapping.sourceColumn - lastSourceColumn);
lastSourceColumn = mapping.sourceColumn;
needComma = true;
}
}
v3 = {
version: 3,
file: options.generatedFile || '',
sourceRoot: options.sourceRoot || '',
sources: options.sourceFiles || [''],
names: [],
mappings: buffer
};
if (options.inlineMap) {
v3.sourcesContent = [code];
}
return v3;
}
v3 = {
version: 3,
file: options.generatedFile || '',
sourceRoot: options.sourceRoot || '',
sources: options.sourceFiles || [''],
names: [],
mappings: buffer
};
if (options.inlineMap) {
v3.sourcesContent = [code];
encodeVlq(value) {
var answer, nextChunk, signBit, valueToEncode;
answer = '';
signBit = value < 0 ? 1 : 0;
valueToEncode = (Math.abs(value) << 1) + signBit;
while (valueToEncode || !answer) {
nextChunk = valueToEncode & VLQ_VALUE_MASK;
valueToEncode = valueToEncode >> VLQ_SHIFT;
if (valueToEncode) {
nextChunk |= VLQ_CONTINUATION_BIT;
}
answer += this.encodeBase64(nextChunk);
}
return answer;
}
return v3;
encodeBase64(value) {
return BASE64_CHARS[value] || (function() {
throw new Error(`Cannot Base64 encode value: ${value}`);
})();
}
};
VLQ_SHIFT = 5;
@@ -116,30 +139,8 @@
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - 1;
SourceMap.prototype.encodeVlq = function(value) {
var answer, nextChunk, signBit, valueToEncode;
answer = '';
signBit = value < 0 ? 1 : 0;
valueToEncode = (Math.abs(value) << 1) + signBit;
while (valueToEncode || !answer) {
nextChunk = valueToEncode & VLQ_VALUE_MASK;
valueToEncode = valueToEncode >> VLQ_SHIFT;
if (valueToEncode) {
nextChunk |= VLQ_CONTINUATION_BIT;
}
answer += this.encodeBase64(nextChunk);
}
return answer;
};
BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
SourceMap.prototype.encodeBase64 = function(value) {
return BASE64_CHARS[value] || (function() {
throw new Error(`Cannot Base64 encode value: ${value}`);
})();
};
return SourceMap;
})();

File diff suppressed because it is too large Load Diff

View File

@@ -449,7 +449,7 @@ test "#1591, #1101: splatted expressions in destructuring assignment must be ass
test "#1643: splatted accesses in destructuring assignments should not be declared as variables", ->
nonce = {}
accesses = ['o.a', 'o["a"]', '(o.a)', '(o.a).a', '@o.a', 'C::a', 'C::', 'f().a', 'o?.a', 'o?.a.b', 'f?().a']
accesses = ['o.a', 'o["a"]', '(o.a)', '(o.a).a', '@o.a', 'C::a', 'f().a', 'o?.a', 'o?.a.b', 'f?().a']
for access in accesses
for i,j in [1,2,3] #position can matter
code =

View File

@@ -191,3 +191,20 @@ test "implicit call with `await`", ->
a = addOne await 3
eq a, 4
test "async methods in classes", ->
class Base
@static: ->
await 1
method: ->
await 2
eq await Base.static(), 1
eq await new Base().method(), 2
class Child extends Base
@static: -> super
method: -> super
eq await Child.static(), 1
eq await new Child().method(), 2

View File

@@ -4,6 +4,7 @@
# * Class Definition
# * Class Instantiation
# * Inheritance and Super
# * ES2015+ Class Interoperability
test "classes with a four-level inheritance chain", ->
@@ -26,7 +27,9 @@ test "classes with a four-level inheritance chain", ->
@array = [1, 2, 3]
class ThirdChild extends SecondChild
constructor: -> thirdCtor.call this
constructor: ->
super()
thirdCtor.call this
# Gratuitous comment for testing.
func: (string) ->
@@ -66,25 +69,6 @@ test "constructors with inheritance and super", ->
ok (new SubClass).prop is 'top-super-sub'
test "Overriding the static property new doesn't clobber Function::new", ->
class OneClass
@new: 'new'
function: 'function'
constructor: (name) -> @name = name
class TwoClass extends OneClass
delete TwoClass.new
Function.prototype.new = -> new this arguments...
ok (TwoClass.new('three')).name is 'three'
ok (new OneClass).function is 'function'
ok OneClass.new is 'new'
delete Function.prototype.new
test "basic classes, again, but in the manual prototype style", ->
Base = ->
@@ -464,7 +448,7 @@ test "ensure that constructors invoked with splats return a new object", ->
# Ensure that constructors invoked with splats cache the function.
called = 0
get = -> if called++ then false else class Type
new get() args...
new (get()) args...
test "`new` shouldn't add extra parens", ->
@@ -480,6 +464,7 @@ test "`new` works against bare function", ->
test "#1182: a subclass should be able to set its constructor to an external function", ->
ctor = ->
@val = 1
return
class A
class B extends A
constructor: ctor
@@ -498,7 +483,7 @@ test "#1313: misplaced __extends", ->
class A
class B extends A
prop: nonce
constructor: ->
constructor: -> super
eq nonce, B::prop
test "#1182: execution order needs to be considered as well", ->
@@ -738,21 +723,21 @@ test "#2599: other typed constructors should be inherited", ->
ok (new Derived) not instanceof Base
ok (new Base) not instanceof Base
test "#2359: extending native objects that use other typed constructors requires defining a constructor", ->
class BrokenArray extends Array
method: -> 'no one will call me'
test "extending native objects works with and without defining a constructor", ->
class MyArray extends Array
method: -> 'yes!'
brokenArray = new BrokenArray
ok brokenArray not instanceof BrokenArray
ok typeof brokenArray.method is 'undefined'
myArray = new MyArray
ok myArray instanceof MyArray
ok 'yes!', myArray.method()
class WorkingArray extends Array
class OverrideArray extends Array
constructor: -> super
method: -> 'yes!'
workingArray = new WorkingArray
ok workingArray instanceof WorkingArray
eq 'yes!', workingArray.method()
overrideArray = new OverrideArray
ok overrideArray instanceof OverrideArray
eq 'yes!', overrideArray.method()
test "#2782: non-alphanumeric-named bound functions", ->
@@ -855,7 +840,7 @@ test "#1392 calling `super` in methods defined on namespaced classes", ->
eq 1, count
class C
@a: ->
@a: (->)
@a extends Base
@a::m = -> super
eq 5, (new C.a).m()
@@ -898,3 +883,811 @@ test "dynamic method names and super", ->
class C extends B
m: -> super
eq 5, (new C).m()
# ES2015+ class interoperability
# Based on https://github.com/balupton/es6-javascript-class-interop
# Helper functions to generate true ES classes to extend:
getBasicClass = ->
```
class BasicClass {
constructor (greeting) {
this.greeting = greeting || 'hi'
}
}
```
BasicClass
getExtendedClass = (BaseClass) ->
```
class ExtendedClass extends BaseClass {
constructor (greeting, name) {
super(greeting || 'hello')
this.name = name
}
}
```
ExtendedClass
test "can instantiate a basic ES class", ->
BasicClass = getBasicClass()
i = new BasicClass 'howdy!'
eq i.greeting, 'howdy!'
test "can instantiate an extended ES class", ->
BasicClass = getBasicClass()
ExtendedClass = getExtendedClass BasicClass
i = new ExtendedClass 'yo', 'buddy'
eq i.greeting, 'yo'
eq i.name, 'buddy'
test "can extend a basic ES class", ->
BasicClass = getBasicClass()
class ExtendedClass extends BasicClass
constructor: (@name) ->
super()
i = new ExtendedClass 'dude'
eq i.name, 'dude'
test "can extend an extended ES class", ->
BasicClass = getBasicClass()
ExtendedClass = getExtendedClass BasicClass
class ExtendedExtendedClass extends ExtendedClass
constructor: (@value) ->
super()
getDoubledValue: ->
@value * 2
i = new ExtendedExtendedClass 7
eq i.getDoubledValue(), 14
test "CoffeeScript class can be extended in ES", ->
class CoffeeClass
constructor: (@favoriteDrink = 'latte', @size = 'grande') ->
getDrinkOrder: ->
"#{@size} #{@favoriteDrink}"
```
class ECMAScriptClass extends CoffeeClass {
constructor (favoriteDrink) {
super(favoriteDrink);
this.favoriteDrink = this.favoriteDrink + ' with a dash of semicolons';
}
}
```
e = new ECMAScriptClass 'coffee'
eq e.getDrinkOrder(), 'grande coffee with a dash of semicolons'
test "extended CoffeeScript class can be extended in ES", ->
class CoffeeClass
constructor: (@favoriteDrink = 'latte') ->
class CoffeeClassWithDrinkOrder extends CoffeeClass
constructor: (@favoriteDrink, @size = 'grande') ->
super()
getDrinkOrder: ->
"#{@size} #{@favoriteDrink}"
```
class ECMAScriptClass extends CoffeeClassWithDrinkOrder {
constructor (favoriteDrink) {
super(favoriteDrink);
this.favoriteDrink = this.favoriteDrink + ' with a dash of semicolons';
}
}
```
e = new ECMAScriptClass 'coffee'
eq e.getDrinkOrder(), 'grande coffee with a dash of semicolons'
test "`this` access after `super` in extended classes", ->
class Base
class Test extends Base
constructor: (param, @param) ->
eq param, nonce
result = { super: super(), @param, @method }
eq result.super, this
eq result.param, @param
eq result.method, @method
ok result.method isnt Test::method
method: =>
nonce = {}
new Test nonce, {}
test "`@`-params and bound methods with multiple `super` paths (blocks)", ->
nonce = {}
class Base
constructor: (@name) ->
class Test extends Base
constructor: (param, @param) ->
if param
super 'param'
eq @name, 'param'
else
super 'not param'
eq @name, 'not param'
eq @param, nonce
ok @method isnt Test::method
method: =>
new Test true, nonce
new Test false, nonce
test "`@`-params and bound methods with multiple `super` paths (expressions)", ->
nonce = {}
class Base
constructor: (@name) ->
class Test extends Base
constructor: (param, @param) ->
# Contrived example: force each path into an expression with inline assertions
if param
result = (
eq (super 'param'), @;
eq @name, 'param';
eq @param, nonce;
ok @method isnt Test::method
)
else
result = (
eq (super 'not param'), @;
eq @name, 'not param';
eq @param, nonce;
ok @method isnt Test::method
)
method: =>
new Test true, nonce
new Test false, nonce
test "constructor super in arrow functions", ->
class Test extends (class)
constructor: (@param) ->
do => super
eq @param, nonce
new Test nonce = {}
# Ensure that we always throw if we experience more than one super()
# call in a constructor. This ends up being a runtime error.
# Should be caught at compile time.
test "multiple super calls", ->
throwsA = """
class A
constructor: (@drink) ->
make: -> "Making a #{@drink}"
class MultiSuper extends A
constructor: (drink) ->
super(drink)
super(drink)
@newDrink = drink
new MultiSuper('Late').make()
"""
throws -> CoffeeScript.run throwsA, bare: yes
# Basic test to ensure we can pass @params in a constuctor and
# inheritance works correctly
test "@ params", ->
class A
constructor: (@drink, @shots, @flavor) ->
make: -> "Making a #{@flavor} #{@drink} with #{@shots} shot(s)"
a = new A('Machiato', 2, 'chocolate')
eq a.make(), "Making a chocolate Machiato with 2 shot(s)"
class B extends A
b = new B('Machiato', 2, 'chocolate')
eq b.make(), "Making a chocolate Machiato with 2 shot(s)"
# Ensure we can accept @params with default parameters in a constructor
test "@ params with defaults in a constructor", ->
class A
# Multiple @ params with defaults
constructor: (@drink = 'Americano', @shots = '1', @flavor = 'caramel') ->
make: -> "Making a #{@flavor} #{@drink} with #{@shots} shot(s)"
a = new A()
eq a.make(), "Making a caramel Americano with 1 shot(s)"
# Ensure we can handle default constructors with class params
test "@ params with class params", ->
class Beverage
drink: 'Americano'
shots: '1'
flavor: 'caramel'
class A
# Class creation as a default param with `this`
constructor: (@drink = new Beverage()) ->
a = new A()
eq a.drink.drink, 'Americano'
beverage = new Beverage
class B
# class costruction with a default external param
constructor: (@drink = beverage) ->
b = new B()
eq b.drink.drink, 'Americano'
class C
# Default constructor with anonymous empty class
constructor: (@meta = class) ->
c = new C()
ok c.meta instanceof Function
test "@ params without super, including errors", ->
classA = """
class A
constructor: (@drink) ->
make: -> "Making a #{@drink}"
a = new A('Machiato')
"""
throwsB = """
class B extends A
#implied super
constructor: (@drink) ->
b = new B('Machiato')
"""
throws -> CoffeeScript.compile classA + throwsB, bare: yes
test "@ params super race condition", ->
classA = """
class A
constructor: (@drink) ->
make: -> "Making a #{@drink}"
"""
throwsB = """
class B extends A
constructor: (@params) ->
b = new B('Machiato')
"""
throws -> CoffeeScript.compile classA + throwsB, bare: yes
# Race condition with @ and super
throwsC = """
class C extends A
constructor: (@params) ->
super(@params)
c = new C('Machiato')
"""
throws -> CoffeeScript.compile classA + throwsC, bare: yes
test "@ with super call", ->
class D
make: -> "Making a #{@drink}"
class E extends D
constructor: (@drink) ->
super()
e = new E('Machiato')
eq e.make(), "Making a Machiato"
test "@ with splats and super call", ->
class A
make: -> "Making a #{@drink}"
class B extends A
constructor: (@drink...) ->
super()
B = new B('Machiato')
eq B.make(), "Making a Machiato"
test "super and external constructors", ->
# external constructor with @ param is allowed
ctorA = (@drink) ->
class A
constructor: ctorA
make: -> "Making a #{@drink}"
a = new A('Machiato')
eq a.make(), "Making a Machiato"
# External constructor with super
throwsC = """
class B
constructor: (@drink) ->
make: -> "Making a #{@drink}"
ctorC = (drink) ->
super(drink)
class C extends B
constructor: ctorC
c = new C('Machiato')
"""
throws -> CoffeeScript.compile throwsC, bare: yes
test "super in external prototype", ->
class A
constructor: (@drink) ->
make: -> "Making a #{@drink}"
class B extends A
B::make = (@flavor) -> super() + " with #{@flavor}"
b = new B('Machiato')
eq b.make('caramel'), "Making a Machiato with caramel"
# Fails, bound
# TODO: Could this throw a compile error?
class C extends A
C::make = (@flavor) => super() + " with #{@flavor}"
c = new C('Machiato')
ok c.make('caramel') isnt "Making a Machiato with caramel"
test "bound functions without super", ->
# Bound function with @
# Throw on compile, since bound
# constructors are illegal
throwsA = """
class A
constructor: (drink) =>
@drink = drink
"""
throws -> CoffeeScript.compile throwsA, bare: yes
test "super in a bound function in a constructor", ->
throwsB = """
class A
class B extends A
constructor: do => super
"""
throws -> CoffeeScript.compile throwsB, bare: yes
test "super in a bound function", ->
class A
constructor: (@drink) ->
make: -> "Making a #{@drink}"
class B extends A
make: (@flavor) =>
super + " with #{@flavor}"
b = new B('Machiato')
eq b.make('vanilla'), "Making a Machiato with vanilla"
# super in a bound function in a bound function
class C extends A
make: (@flavor) =>
func = () =>
super + " with #{@flavor}"
func()
c = new C('Machiato')
eq c.make('vanilla'), "Making a Machiato with vanilla"
# bound function in a constructor
class D extends A
constructor: (drink) ->
super(drink)
x = =>
eq @drink, "Machiato"
x()
d = new D('Machiato')
eq d.make(), "Making a Machiato"
# duplicate
test "super in a try/catch", ->
classA = """
class A
constructor: (param) ->
throw "" unless param
"""
throwsB = """
class B extends A
constructor: ->
try
super
"""
throwsC = """
ctor = ->
try
super
class C extends A
constructor: ctor
"""
throws -> CoffeeScript.run classA + throwsB, bare: yes
throws -> CoffeeScript.run classA + throwsC, bare: yes
test "mixed ES6 and CS6 classes with a four-level inheritance chain", ->
# Extended test
# ES2015+ class interoperability
```
class Base {
constructor (greeting) {
this.greeting = greeting || 'hi';
}
func (string) {
return 'zero/' + string;
}
static staticFunc (string) {
return 'static/' + string;
}
}
```
class FirstChild extends Base
func: (string) ->
super('one/') + string
```
class SecondChild extends FirstChild {
func (string) {
return super.func('two/' + string);
}
}
```
thirdCtor = ->
@array = [1, 2, 3]
class ThirdChild extends SecondChild
constructor: ->
super()
thirdCtor.call this
func: (string) ->
super('three/') + string
result = (new ThirdChild).func 'four'
ok result is 'zero/one/two/three/four'
ok Base.staticFunc('word') is 'static/word'
# exercise extends in a nested class
test "nested classes with super", ->
class Outer
constructor: ->
@label = 'outer'
class @Inner
constructor: ->
@label = 'inner'
class @ExtendedInner extends @Inner
constructor: ->
tmp = super()
@label = tmp.label + ' extended'
@extender: () =>
class ExtendedSelf extends @
constructor: ->
tmp = super()
@label = tmp.label + ' from this'
new ExtendedSelf
eq (new Outer).label, 'outer'
eq (new Outer.Inner).label, 'inner'
eq (new Outer.ExtendedInner).label, 'inner extended'
eq (Outer.extender()).label, 'outer from this'
test "Static methods generate 'static' keywords", ->
compile = """
class CheckStatic
constructor: (@drink) ->
@className: -> 'CheckStatic'
c = new CheckStatic('Machiato')
"""
result = CoffeeScript.compile compile, bare: yes
ok result.match(' static ')
test "Static methods in nested classes", ->
class Outer
@name: -> 'Outer'
class @Inner
@name: -> 'Inner'
eq Outer.name(), 'Outer'
eq Outer.Inner.name(), 'Inner'
test "mixed constructors with inheritance and ES6 super", ->
identity = (f) -> f
class TopClass
constructor: (arg) ->
@prop = 'top-' + arg
```
class SuperClass extends TopClass {
constructor (arg) {
identity(super('super-' + arg));
}
}
```
class SubClass extends SuperClass
constructor: ->
identity super 'sub'
ok (new SubClass).prop is 'top-super-sub'
test "ES6 static class methods can be overriden", ->
class A
@name: -> 'A'
class B extends A
@name: -> 'B'
eq A.name(), 'A'
eq B.name(), 'B'
# If creating static by direct assignment rather than ES6 static keyword
test "ES6 Static methods should set `this` to undefined // ES6 ", ->
class A
@test: ->
eq this, undefined
# Ensure that our object prototypes work with ES6
test "ES6 prototypes can be overriden", ->
class A
className: 'classA'
```
class B {
test () {return "B";};
}
```
b = new B
a = new A
eq a.className, 'classA'
eq b.test(), 'B'
Object.setPrototypeOf(b, a)
eq b.className, 'classA'
# This shouldn't throw,
# as we only change inheritance not object construction
# This may be an issue with ES, rather than CS construction?
#eq b.test(), 'B'
class D extends B
B::test = () -> 'D'
eq (new D).test(), 'D'
# TODO: implement this error check
# test "ES6 conformance to extending non-classes", ->
# A = (@title) ->
# 'Title: ' + @
# class B extends A
# b = new B('caffeinated')
# eq b.title, 'caffeinated'
# # Check inheritance chain
# A::getTitle = () -> @title
# eq b.getTitle(), 'caffeinated'
# throwsC = """
# C = {title: 'invalid'}
# class D extends {}
# """
# # This should catch on compile and message should be "class can only extend classes and functions."
# throws -> CoffeeScript.run throwsC, bare: yes
# TODO: Evaluate future compliance with "strict mode";
# test "Class function environment should be in `strict mode`, ie as if 'use strict' was in use", ->
# class A
# # this might be a meaningless test, since these are likely to be runtime errors and different
# # for every browser. Thoughts?
# constructor: () ->
# # Ivalid: prop reassignment
# @state = {prop: [1], prop: {a: 'a'}}
# # eval reassignment
# @badEval = eval;
# # Should throw, but doesn't
# a = new A
# TODO: new.target needs support Separate issue
# test "ES6 support for new.target (functions and constructors)", ->
# throwsA = """
# class A
# constructor: () ->
# a = new.target.name
# """
# throws -> CoffeeScript.compile throwsA, bare: yes
test "only one method named constructor allowed", ->
throwsA = """
class A
constructor: (@first) ->
constructor: (@last) ->
"""
throws -> CoffeeScript.compile throwsA, bare: yes
test "If the constructor of a child class does not call super,it should return an object.", ->
nonce = {}
class A
class B extends A
constructor: ->
return nonce
eq nonce, new B
test "super can only exist in extended classes", ->
throwsA = """
class A
constructor: (@name) ->
super()
"""
throws -> CoffeeScript.compile throwsA, bare: yes
# --- CS1 classes compatability breaks ---
test "CS6 Class extends a CS1 compiled class", ->
```
// Generated by CoffeeScript 1.11.1
var BaseCS1, ExtendedCS1,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
BaseCS1 = (function() {
function BaseCS1(drink) {
this.drink = drink;
}
BaseCS1.prototype.make = function() {
return "making a " + this.drink;
};
BaseCS1.className = function() {
return 'BaseCS1';
};
return BaseCS1;
})();
ExtendedCS1 = (function(superClass) {
extend(ExtendedCS1, superClass);
function ExtendedCS1(flavor) {
this.flavor = flavor;
ExtendedCS1.__super__.constructor.call(this, 'cafe ole');
}
ExtendedCS1.prototype.make = function() {
return "making a " + this.drink + " with " + this.flavor;
};
ExtendedCS1.className = function() {
return 'ExtendedCS1';
};
return ExtendedCS1;
})(BaseCS1);
```
class B extends BaseCS1
eq B.className(), 'BaseCS1'
b = new B('machiato')
eq b.make(), "making a machiato"
test "CS6 Class extends an extended CS1 compiled class", ->
```
// Generated by CoffeeScript 1.11.1
var BaseCS1, ExtendedCS1,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
BaseCS1 = (function() {
function BaseCS1(drink) {
this.drink = drink;
}
BaseCS1.prototype.make = function() {
return "making a " + this.drink;
};
BaseCS1.className = function() {
return 'BaseCS1';
};
return BaseCS1;
})();
ExtendedCS1 = (function(superClass) {
extend(ExtendedCS1, superClass);
function ExtendedCS1(flavor) {
this.flavor = flavor;
ExtendedCS1.__super__.constructor.call(this, 'cafe ole');
}
ExtendedCS1.prototype.make = function() {
return "making a " + this.drink + " with " + this.flavor;
};
ExtendedCS1.className = function() {
return 'ExtendedCS1';
};
return ExtendedCS1;
})(BaseCS1);
```
class B extends ExtendedCS1
eq B.className(), 'ExtendedCS1'
b = new B('vanilla')
eq b.make(), "making a cafe ole with vanilla"
test "CS6 Class extends a CS1 compiled class with super()", ->
```
// Generated by CoffeeScript 1.11.1
var BaseCS1, ExtendedCS1,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
BaseCS1 = (function() {
function BaseCS1(drink) {
this.drink = drink;
}
BaseCS1.prototype.make = function() {
return "making a " + this.drink;
};
BaseCS1.className = function() {
return 'BaseCS1';
};
return BaseCS1;
})();
ExtendedCS1 = (function(superClass) {
extend(ExtendedCS1, superClass);
function ExtendedCS1(flavor) {
this.flavor = flavor;
ExtendedCS1.__super__.constructor.call(this, 'cafe ole');
}
ExtendedCS1.prototype.make = function() {
return "making a " + this.drink + " with " + this.flavor;
};
ExtendedCS1.className = function() {
return 'ExtendedCS1';
};
return ExtendedCS1;
})(BaseCS1);
```
class B extends ExtendedCS1
constructor: (@shots) ->
super('caramel')
make: () ->
super + " and #{@shots} shots of espresso"
eq B.className(), 'ExtendedCS1'
b = new B('three')
eq b.make(), "making a cafe ole with caramel and three shots of espresso"

View File

@@ -378,11 +378,15 @@ test "#3132: Place block-comments nicely", ->
var DummyClass;
DummyClass = (function() {
class DummyClass {
/**
* @constructor
*/
function DummyClass() {}
/**
* @constructor
*/
constructor() {}
};
/**

View File

@@ -416,7 +416,7 @@ test "#3795: invalid escapes", ->
assertErrorFormat '''
///a \\u002 0 space///
''', '''
[stdin]:1:6: error: invalid escape sequence \\u002
[stdin]:1:6: error: invalid escape sequence \\u002 \n\
///a \\u002 0 space///
^\^^^^^
'''
@@ -1205,3 +1205,45 @@ test "tagged template literals must be called by an identifier", ->
1"""#{b}"""
^
'''
test "constructor functions can't be async", ->
assertErrorFormat 'class then constructor: -> await x', '''
[stdin]:1:12: error: Class constructor may not be async
class then constructor: -> await x
^^^^^^^^^^^
'''
test "constructor functions can't be generators", ->
assertErrorFormat 'class then constructor: -> yield', '''
[stdin]:1:12: error: Class constructor may not be a generator
class then constructor: -> yield
^^^^^^^^^^^
'''
test "non-derived constructors can't call super", ->
assertErrorFormat 'class then constructor: -> super', '''
[stdin]:1:28: error: 'super' is only allowed in derived class constructors
class then constructor: -> super
^^^^^
'''
test "derived constructors can't reference `this` before calling super", ->
assertErrorFormat 'class extends A then constructor: -> @', '''
[stdin]:1:38: error: Can't reference 'this' before calling super in derived class constructors
class extends A then constructor: -> @
^
'''
test "derived constructors can't use @params without calling super", ->
assertErrorFormat 'class extends A then constructor: (@a) ->', '''
[stdin]:1:36: error: Can't use @params in derived class constructors without calling super
class extends A then constructor: (@a) ->
^^
'''
test "'super' is not allowed in constructor parameter defaults", ->
assertErrorFormat 'class extends A then constructor: (a = super) ->', '''
[stdin]:1:40: error: 'super' is not allowed in constructor parameter defaults
class extends A then constructor: (a = super) ->
^^^^^
'''

View File

@@ -325,3 +325,20 @@ test "from as a destructured array variable name in a for loop declaration", ->
for [from, to] from a
b.push from
arrayEq b, [1, 3]
test "generator methods in classes", ->
class Base
@static: ->
yield 1
method: ->
yield 2
arrayEq [1], Array.from Base.static()
arrayEq [2], Array.from new Base().method()
class Child extends Base
@static: -> super
method: -> super
arrayEq [1], Array.from Child.static()
arrayEq [2], Array.from new Child().method()

View File

@@ -457,7 +457,7 @@ test "export class", ->
baz: ->
console.log 'hello, world!'"""
output = toJS input
ok /^export (class foo|var foo = \(function)/.test toJS input
ok /^export (var foo = class foo|var foo = \(function)/.test toJS input
test "export class that extends", ->
input = """

View File

@@ -330,7 +330,7 @@ test "floor division operator", ->
test "floor division operator compound assignment", ->
a = 7
a //= 2
a //= 1 + 1
eq 3, a
test "modulo operator", ->
@@ -436,3 +436,27 @@ test "#3598: Unary + and - coerce the operand once when it is an identifier", ->
ok ~a in [0, -2]
assertOneCoercion (a) ->
ok a / 2 in [0, 0.5]
test "'new' target", ->
nonce = {}
ctor = -> nonce
eq (new ctor), nonce
eq (new ctor()), nonce
ok new class
ctor = class
ok (new ctor) instanceof ctor
ok (new ctor()) instanceof ctor
# Force an executable class body
ctor = class then a = 1
ok (new ctor) instanceof ctor
get = -> ctor
ok (new get()) not instanceof ctor
ok (new (get())()) instanceof ctor
# classes must be called with `new`. In this case `new` applies to `get` only
throws -> new get()()

View File

@@ -8,6 +8,7 @@ Stream = require 'stream'
class MockInputStream extends Stream
constructor: ->
super()
@readable = true
resume: ->
@@ -17,6 +18,7 @@ class MockInputStream extends Stream
class MockOutputStream extends Stream
constructor: ->
super()
@writable = true
@written = []