1.9.3~dfsg/0000755000000000000000000000000012531364553011275 5ustar rootroot1.9.3~dfsg/lib/0000755000000000000000000000000012531364553012043 5ustar rootroot1.9.3~dfsg/lib/coffee-script/0000755000000000000000000000000012531364553014574 5ustar rootroot1.9.3~dfsg/lib/coffee-script/lexer.js0000644000000000000000000010306112531364553016252 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HERECOMMENT_ILLEGAL, HEREDOC_DOUBLE, HEREDOC_INDENT, HEREDOC_SINGLE, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INVALID_ESCAPE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LEADING_BLANK_LINE, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTI_DENT, NOT_REGEX, NUMBER, OPERATOR, POSSIBLY_DIVISION, REGEX, REGEX_FLAGS, REGEX_ILLEGAL, RELATION, RESERVED, Rewriter, SHIFT, SIMPLE_STRING_OMIT, STRICT_PROSCRIBED, STRING_DOUBLE, STRING_OMIT, STRING_SINGLE, STRING_START, TRAILING_BLANK_LINE, TRAILING_SPACES, UNARY, UNARY_MATH, VALID_FLAGS, WHITESPACE, compact, count, invertLiterate, key, locationDataToString, ref, ref1, repeat, starts, throwSyntaxError, 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; }; ref = require('./rewriter'), Rewriter = ref.Rewriter, INVERSES = ref.INVERSES; 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) { var consumed, end, i, ref2; if (opts == null) { opts = {}; } this.literate = opts.literate; this.indent = 0; this.baseIndent = 0; this.indebt = 0; this.outdebt = 0; this.indents = []; this.ends = []; this.tokens = []; this.chunkLine = opts.line || 0; this.chunkColumn = opts.column || 0; code = this.clean(code); i = 0; while (this.chunk = code.slice(i)) { consumed = this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken(); ref2 = this.getLineAndColumnFromChunk(consumed), this.chunkLine = ref2[0], this.chunkColumn = ref2[1]; i += consumed; if (opts.untilBalanced && this.ends.length === 0) { return { tokens: this.tokens, index: i }; } } this.closeIndentation(); if (end = this.ends.pop()) { this.error("missing " + end.tag, end.origin[2]); } if (opts.rewrite === false) { return this.tokens; } return (new Rewriter).rewrite(this.tokens); }; Lexer.prototype.clean = function(code) { if (code.charCodeAt(0) === BOM) { code = code.slice(1); } code = code.replace(/\r/g, '').replace(TRAILING_SPACES, ''); if (WHITESPACE.test(code)) { code = "\n" + code; this.chunkLine--; } if (this.literate) { code = invertLiterate(code); } return code; }; Lexer.prototype.identifierToken = function() { var alias, colon, colonOffset, forcedIdentifier, id, idLength, input, match, poppedToken, prev, ref2, ref3, ref4, ref5, tag, tagToken; if (!(match = IDENTIFIER.exec(this.chunk))) { return 0; } input = match[0], id = match[1], colon = match[2]; idLength = id.length; poppedToken = void 0; if (id === 'own' && this.tag() === 'FOR') { this.token('OWN', id); return id.length; } if (id === 'from' && this.tag() === 'YIELD') { this.token('FROM', id); return id.length; } ref2 = this.tokens, prev = ref2[ref2.length - 1]; forcedIdentifier = colon || (prev != null) && (((ref3 = prev[0]) === '.' || ref3 === '?.' || ref3 === '::' || ref3 === '?::') || !prev.spaced && prev[0] === '@'); tag = 'IDENTIFIER'; if (!forcedIdentifier && (indexOf.call(JS_KEYWORDS, id) >= 0 || indexOf.call(COFFEE_KEYWORDS, id) >= 0)) { tag = id.toUpperCase(); if (tag === 'WHEN' && (ref4 = this.tag(), indexOf.call(LINE_BREAK, ref4) >= 0)) { tag = 'LEADING_WHEN'; } else if (tag === 'FOR') { this.seenFor = true; } else if (tag === 'UNLESS') { tag = 'IF'; } else if (indexOf.call(UNARY, tag) >= 0) { tag = 'UNARY'; } else if (indexOf.call(RELATION, tag) >= 0) { if (tag !== 'INSTANCEOF' && this.seenFor) { tag = 'FOR' + tag; this.seenFor = false; } else { tag = 'RELATION'; if (this.value() === '!') { poppedToken = this.tokens.pop(); id = '!' + id; } } } } if (indexOf.call(JS_FORBIDDEN, id) >= 0) { if (forcedIdentifier) { tag = 'IDENTIFIER'; id = new String(id); id.reserved = true; } else if (indexOf.call(RESERVED, id) >= 0) { this.error("reserved word '" + id + "'", { length: id.length }); } } if (!forcedIdentifier) { if (indexOf.call(COFFEE_ALIASES, id) >= 0) { alias = id; id = COFFEE_ALIAS_MAP[id]; } tag = (function() { switch (id) { case '!': return 'UNARY'; case '==': case '!=': return 'COMPARE'; case '&&': case '||': return 'LOGIC'; case 'true': case 'false': return 'BOOL'; case 'break': case 'continue': return 'STATEMENT'; default: return tag; } })(); } tagToken = this.token(tag, id, 0, idLength); if (alias) { tagToken.origin = [tag, alias, tagToken[2]]; } tagToken.variable = !forcedIdentifier; if (poppedToken) { ref5 = [poppedToken[2].first_line, poppedToken[2].first_column], tagToken[2].first_line = ref5[0], tagToken[2].first_column = ref5[1]; } if (colon) { colonOffset = input.lastIndexOf(':'); this.token(':', ':', colonOffset, colon.length); } return input.length; }; Lexer.prototype.numberToken = function() { var binaryLiteral, lexedLength, match, number, octalLiteral; if (!(match = NUMBER.exec(this.chunk))) { return 0; } number = match[0]; lexedLength = number.length; if (/^0[BOX]/.test(number)) { this.error("radix prefix in '" + number + "' must be lowercase", { offset: 1 }); } else if (/E/.test(number) && !/^0x/.test(number)) { this.error("exponential notation in '" + number + "' must be indicated with a lowercase 'e'", { offset: number.indexOf('E') }); } else if (/^0\d*[89]/.test(number)) { this.error("decimal literal '" + number + "' must not be prefixed with '0'", { length: lexedLength }); } else if (/^0\d+/.test(number)) { this.error("octal literal '" + number + "' must be prefixed with '0o'", { length: lexedLength }); } if (octalLiteral = /^0o([0-7]+)/.exec(number)) { number = '0x' + parseInt(octalLiteral[1], 8).toString(16); } if (binaryLiteral = /^0b([01]+)/.exec(number)) { number = '0x' + parseInt(binaryLiteral[1], 2).toString(16); } this.token('NUMBER', number, 0, lexedLength); return lexedLength; }; Lexer.prototype.stringToken = function() { 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) { return 0; } regex = (function() { switch (quote) { case "'": return STRING_SINGLE; case '"': return STRING_DOUBLE; case "'''": return HEREDOC_SINGLE; case '"""': return HEREDOC_DOUBLE; } })(); heredoc = quote.length === 3; ref2 = this.matchWithInterpolations(regex, quote), tokens = ref2.tokens, end = ref2.index; $ = tokens.length - 1; delimiter = quote.charAt(0); if (heredoc) { indent = null; doc = ((function() { var j, len, results; results = []; for (i = j = 0, len = tokens.length; j < len; i = ++j) { token = tokens[i]; if (token[0] === 'NEOSTRING') { results.push(token[1]); } } return results; })()).join('#{}'); while (match = HEREDOC_INDENT.exec(doc)) { attempt = match[1]; if (indent === null || (0 < (ref3 = attempt.length) && ref3 < indent.length)) { indent = attempt; } } if (indent) { indentRegex = RegExp("^" + indent, "gm"); } this.mergeInterpolationTokens(tokens, { delimiter: delimiter }, (function(_this) { return function(value, i) { value = _this.formatString(value); if (i === 0) { value = value.replace(LEADING_BLANK_LINE, ''); } if (i === $) { value = value.replace(TRAILING_BLANK_LINE, ''); } if (indentRegex) { value = value.replace(indentRegex, ''); } return value; }; })(this)); } else { this.mergeInterpolationTokens(tokens, { delimiter: delimiter }, (function(_this) { return function(value, i) { value = _this.formatString(value); value = value.replace(SIMPLE_STRING_OMIT, function(match, offset) { if ((i === 0 && offset === 0) || (i === $ && offset + match.length === value.length)) { return ''; } else { return ' '; } }); return value; }; })(this)); } return end; }; Lexer.prototype.commentToken = function() { var comment, here, match; if (!(match = this.chunk.match(COMMENT))) { return 0; } comment = match[0], here = match[1]; if (here) { if (match = HERECOMMENT_ILLEGAL.exec(comment)) { this.error("block comments cannot contain " + match[0], { offset: match.index, length: match[0].length }); } if (here.indexOf('\n') >= 0) { here = here.replace(RegExp("\\n" + (repeat(' ', this.indent)), "g"), '\n'); } this.token('HERECOMMENT', here, 0, comment.length); } return comment.length; }; Lexer.prototype.jsToken = function() { var match, script; if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) { return 0; } this.token('JS', (script = match[0]).slice(1, -1), 0, script.length); return script.length; }; Lexer.prototype.regexToken = function() { var body, closed, end, flags, index, match, origin, prev, ref2, ref3, ref4, regex, tokens; switch (false) { case !(match = REGEX_ILLEGAL.exec(this.chunk)): this.error("regular expressions cannot begin with " + match[2], { offset: match.index + match[1].length }); break; case !(match = this.matchWithInterpolations(HEREGEX, '///')): tokens = match.tokens, index = match.index; break; case !(match = REGEX.exec(this.chunk)): regex = match[0], body = match[1], closed = match[2]; this.validateEscapes(body, { isRegex: true, offsetInChunk: 1 }); index = regex.length; ref2 = this.tokens, prev = ref2[ref2.length - 1]; if (prev) { if (prev.spaced && (ref3 = prev[0], indexOf.call(CALLABLE, ref3) >= 0)) { if (!closed || POSSIBLY_DIVISION.test(regex)) { return 0; } } else if (ref4 = prev[0], indexOf.call(NOT_REGEX, ref4) >= 0) { return 0; } } if (!closed) { this.error('missing / (unclosed regex)'); } break; default: return 0; } flags = REGEX_FLAGS.exec(this.chunk.slice(index))[0]; end = index + flags.length; origin = this.makeToken('REGEX', null, 0, end); switch (false) { case !!VALID_FLAGS.test(flags): this.error("invalid regular expression flags " + flags, { offset: index, length: flags.length }); break; case !(regex || tokens.length === 1): if (body == null) { body = this.formatHeregex(tokens[0][1]); } this.token('REGEX', "" + (this.makeDelimitedLiteral(body, { delimiter: '/' })) + flags, 0, end, origin); break; default: this.token('REGEX_START', '(', 0, 0, origin); this.token('IDENTIFIER', 'RegExp', 0, 0); this.token('CALL_START', '(', 0, 0); this.mergeInterpolationTokens(tokens, { delimiter: '"', double: true }, this.formatHeregex); if (flags) { this.token(',', ',', index, 0); this.token('STRING', '"' + flags + '"', index, flags.length); } this.token(')', ')', end, 0); this.token('REGEX_END', ')', end, 0); } return end; }; Lexer.prototype.lineToken = function() { var diff, indent, match, noNewlines, size; if (!(match = MULTI_DENT.exec(this.chunk))) { return 0; } indent = match[0]; this.seenFor = false; size = indent.length - 1 - indent.lastIndexOf('\n'); noNewlines = this.unfinished(); if (size - this.indebt === this.indent) { if (noNewlines) { this.suppressNewlines(); } else { this.newlineToken(0); } return indent.length; } if (size > this.indent) { if (noNewlines) { this.indebt = size - this.indent; this.suppressNewlines(); return indent.length; } if (!this.tokens.length) { this.baseIndent = this.indent = size; return indent.length; } diff = size - this.indent + this.outdebt; this.token('INDENT', diff, indent.length - size, size); this.indents.push(diff); this.ends.push({ tag: 'OUTDENT' }); this.outdebt = this.indebt = 0; this.indent = size; } else if (size < this.baseIndent) { this.error('missing indentation', { offset: indent.length }); } else { this.indebt = 0; this.outdentToken(this.indent - size, noNewlines, indent.length); } return indent.length; }; Lexer.prototype.outdentToken = function(moveOut, noNewlines, outdentLength) { var decreasedIndent, dent, lastIndent, ref2; decreasedIndent = this.indent - moveOut; while (moveOut > 0) { lastIndent = this.indents[this.indents.length - 1]; if (!lastIndent) { moveOut = 0; } else if (lastIndent === this.outdebt) { moveOut -= this.outdebt; this.outdebt = 0; } else if (lastIndent < this.outdebt) { this.outdebt -= lastIndent; moveOut -= lastIndent; } else { dent = this.indents.pop() + this.outdebt; if (outdentLength && (ref2 = this.chunk[outdentLength], indexOf.call(INDENTABLE_CLOSERS, ref2) >= 0)) { decreasedIndent -= dent - moveOut; moveOut = dent; } this.outdebt = 0; this.pair('OUTDENT'); this.token('OUTDENT', moveOut, 0, outdentLength); moveOut -= dent; } } if (dent) { this.outdebt -= moveOut; } while (this.value() === ';') { this.tokens.pop(); } if (!(this.tag() === 'TERMINATOR' || noNewlines)) { this.token('TERMINATOR', '\n', outdentLength, 0); } this.indent = decreasedIndent; return this; }; Lexer.prototype.whitespaceToken = function() { var match, nline, prev, ref2; if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) { return 0; } ref2 = this.tokens, prev = ref2[ref2.length - 1]; if (prev) { prev[match ? 'spaced' : 'newLine'] = true; } if (match) { return match[0].length; } else { return 0; } }; Lexer.prototype.newlineToken = function(offset) { while (this.value() === ';') { this.tokens.pop(); } if (this.tag() !== 'TERMINATOR') { this.token('TERMINATOR', '\n', offset, 0); } return this; }; Lexer.prototype.suppressNewlines = function() { if (this.value() === '\\') { this.tokens.pop(); } return this; }; Lexer.prototype.literalToken = function() { var match, prev, ref2, ref3, ref4, ref5, ref6, tag, token, value; if (match = OPERATOR.exec(this.chunk)) { value = match[0]; if (CODE.test(value)) { this.tagParameters(); } } else { value = this.chunk.charAt(0); } tag = value; ref2 = this.tokens, prev = ref2[ref2.length - 1]; if (value === '=' && prev) { if (!prev[1].reserved && (ref3 = prev[1], indexOf.call(JS_FORBIDDEN, ref3) >= 0)) { if (prev.origin) { prev = prev.origin; } this.error("reserved word '" + prev[1] + "' can't be assigned", prev[2]); } if ((ref4 = prev[1]) === '||' || ref4 === '&&') { prev[0] = 'COMPOUND_ASSIGN'; prev[1] += '='; return value.length; } } if (value === ';') { this.seenFor = false; tag = 'TERMINATOR'; } else if (indexOf.call(MATH, value) >= 0) { tag = 'MATH'; } else if (indexOf.call(COMPARE, value) >= 0) { tag = 'COMPARE'; } else if (indexOf.call(COMPOUND_ASSIGN, value) >= 0) { tag = 'COMPOUND_ASSIGN'; } else if (indexOf.call(UNARY, value) >= 0) { tag = 'UNARY'; } else if (indexOf.call(UNARY_MATH, value) >= 0) { tag = 'UNARY_MATH'; } else if (indexOf.call(SHIFT, value) >= 0) { tag = 'SHIFT'; } else if (indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) { tag = 'LOGIC'; } else if (prev && !prev.spaced) { if (value === '(' && (ref5 = prev[0], indexOf.call(CALLABLE, ref5) >= 0)) { if (prev[0] === '?') { prev[0] = 'FUNC_EXIST'; } tag = 'CALL_START'; } else if (value === '[' && (ref6 = prev[0], indexOf.call(INDEXABLE, ref6) >= 0)) { tag = 'INDEX_START'; switch (prev[0]) { case '?': prev[0] = 'INDEX_SOAK'; } } } token = this.makeToken(tag, value); switch (value) { case '(': case '{': case '[': this.ends.push({ tag: INVERSES[value], origin: token }); break; case ')': case '}': case ']': this.pair(value); } this.tokens.push(token); return value.length; }; Lexer.prototype.tagParameters = function() { var i, stack, tok, tokens; if (this.tag() !== ')') { return this; } stack = []; tokens = this.tokens; i = tokens.length; tokens[--i][0] = 'PARAM_END'; while (tok = tokens[--i]) { switch (tok[0]) { case ')': stack.push(tok); break; case '(': case 'CALL_START': if (stack.length) { stack.pop(); } else if (tok[0] === '(') { tok[0] = 'PARAM_START'; return this; } else { return this; } } } return this; }; Lexer.prototype.closeIndentation = function() { return this.outdentToken(this.indent); }; Lexer.prototype.matchWithInterpolations = function(regex, delimiter) { var close, column, firstToken, index, lastToken, line, nested, offsetInChunk, open, ref2, ref3, ref4, str, strPart, tokens; tokens = []; offsetInChunk = delimiter.length; if (this.chunk.slice(0, offsetInChunk) !== delimiter) { return null; } str = this.chunk.slice(offsetInChunk); while (true) { strPart = regex.exec(str)[0]; this.validateEscapes(strPart, { isRegex: delimiter.charAt(0) === '/', offsetInChunk: offsetInChunk }); tokens.push(this.makeToken('NEOSTRING', strPart, offsetInChunk)); str = str.slice(strPart.length); offsetInChunk += strPart.length; if (str.slice(0, 2) !== '#{') { break; } ref2 = this.getLineAndColumnFromChunk(offsetInChunk + 1), line = ref2[0], column = ref2[1]; ref3 = new Lexer().tokenize(str.slice(1), { line: line, column: column, untilBalanced: true }), nested = ref3.tokens, index = ref3.index; index += 1; open = nested[0], close = nested[nested.length - 1]; open[0] = open[1] = '('; close[0] = close[1] = ')'; close.origin = ['', 'end of interpolation', close[2]]; if (((ref4 = nested[1]) != null ? ref4[0] : void 0) === 'TERMINATOR') { nested.splice(1, 1); } tokens.push(['TOKENS', nested]); str = str.slice(index); offsetInChunk += index; } if (str.slice(0, delimiter.length) !== delimiter) { this.error("missing " + delimiter, { length: delimiter.length }); } firstToken = tokens[0], lastToken = tokens[tokens.length - 1]; firstToken[2].first_column -= delimiter.length; lastToken[2].last_column += delimiter.length; if (lastToken[1].length === 0) { lastToken[2].last_column -= 1; } return { tokens: tokens, index: offsetInChunk + delimiter.length }; }; Lexer.prototype.mergeInterpolationTokens = function(tokens, options, fn) { var converted, firstEmptyStringIndex, firstIndex, i, j, lastToken, len, locationToken, lparen, plusToken, ref2, rparen, tag, token, tokensToPush, value; if (tokens.length > 1) { lparen = this.token('STRING_START', '(', 0, 0); } firstIndex = this.tokens.length; for (i = j = 0, len = tokens.length; j < len; i = ++j) { token = tokens[i]; tag = token[0], value = token[1]; switch (tag) { case 'TOKENS': if (value.length === 2) { continue; } locationToken = value[0]; tokensToPush = value; break; case 'NEOSTRING': converted = fn(token[1], i); if (converted.length === 0) { if (i === 0) { firstEmptyStringIndex = this.tokens.length; } else { continue; } } if (i === 2 && (firstEmptyStringIndex != null)) { this.tokens.splice(firstEmptyStringIndex, 2); } token[0] = 'STRING'; token[1] = this.makeDelimitedLiteral(converted, options); locationToken = token; tokensToPush = [token]; } if (this.tokens.length > firstIndex) { plusToken = this.token('+', '+'); plusToken[2] = { first_line: locationToken[2].first_line, first_column: locationToken[2].first_column, last_line: locationToken[2].first_line, last_column: locationToken[2].first_column }; } (ref2 = this.tokens).push.apply(ref2, tokensToPush); } if (lparen) { lastToken = tokens[tokens.length - 1]; lparen.origin = [ 'STRING', null, { first_line: lparen[2].first_line, first_column: lparen[2].first_column, last_line: lastToken[2].last_line, last_column: lastToken[2].last_column } ]; rparen = this.token('STRING_END', ')'); return rparen[2] = { first_line: lastToken[2].last_line, first_column: lastToken[2].last_column, last_line: lastToken[2].last_line, last_column: lastToken[2].last_column }; } }; Lexer.prototype.pair = function(tag) { var lastIndent, prev, ref2, ref3, wanted; ref2 = this.ends, prev = ref2[ref2.length - 1]; if (tag !== (wanted = prev != null ? prev.tag : void 0)) { if ('OUTDENT' !== wanted) { this.error("unmatched " + tag); } ref3 = this.indents, lastIndent = ref3[ref3.length - 1]; this.outdentToken(lastIndent, true); return this.pair(tag); } return this.ends.pop(); }; Lexer.prototype.getLineAndColumnFromChunk = function(offset) { var column, lastLine, lineCount, ref2, string; if (offset === 0) { return [this.chunkLine, this.chunkColumn]; } if (offset >= this.chunk.length) { string = this.chunk; } else { string = this.chunk.slice(0, +(offset - 1) + 1 || 9e9); } lineCount = count(string, '\n'); column = this.chunkColumn; if (lineCount > 0) { ref2 = string.split('\n'), lastLine = ref2[ref2.length - 1]; column = lastLine.length; } else { column += string.length; } return [this.chunkLine + lineCount, column]; }; Lexer.prototype.makeToken = function(tag, value, offsetInChunk, length) { var lastCharacter, locationData, ref2, ref3, token; if (offsetInChunk == null) { offsetInChunk = 0; } if (length == null) { length = value.length; } locationData = {}; ref2 = this.getLineAndColumnFromChunk(offsetInChunk), locationData.first_line = ref2[0], locationData.first_column = ref2[1]; lastCharacter = Math.max(0, length - 1); 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) { var token; token = this.makeToken(tag, value, offsetInChunk, length); if (origin) { token.origin = origin; } this.tokens.push(token); return token; }; Lexer.prototype.tag = function() { var ref2, token; ref2 = this.tokens, token = ref2[ref2.length - 1]; return token != null ? token[0] : void 0; }; Lexer.prototype.value = function() { var ref2, token; ref2 = this.tokens, token = ref2[ref2.length - 1]; return token != null ? token[1] : void 0; }; Lexer.prototype.unfinished = function() { var ref2; return LINE_CONTINUER.test(this.chunk) || ((ref2 = this.tag()) === '\\' || ref2 === '.' || ref2 === '?.' || ref2 === '?::' || ref2 === 'UNARY' || ref2 === 'MATH' || ref2 === 'UNARY_MATH' || ref2 === '+' || ref2 === '-' || ref2 === 'YIELD' || ref2 === '**' || ref2 === 'SHIFT' || ref2 === 'RELATION' || ref2 === 'COMPARE' || ref2 === 'LOGIC' || ref2 === 'THROW' || ref2 === 'EXTENDS'); }; Lexer.prototype.formatString = function(str) { return str.replace(STRING_OMIT, '$1'); }; Lexer.prototype.formatHeregex = function(str) { return str.replace(HEREGEX_OMIT, '$1$2'); }; Lexer.prototype.validateEscapes = function(str, options) { var before, hex, invalidEscape, match, message, octal, ref2, unicode; if (options == null) { options = {}; } match = INVALID_ESCAPE.exec(str); if (!match) { return; } match[0], before = match[1], octal = match[2], hex = match[3], unicode = match[4]; if (options.isRegex && octal && octal.charAt(0) !== '0') { return; } message = octal ? "octal escape sequences are not allowed" : "invalid escape sequence"; invalidEscape = "\\" + (octal || hex || unicode); return this.error(message + " " + invalidEscape, { offset: ((ref2 = options.offsetInChunk) != null ? ref2 : 0) + match.index + before.length, length: invalidEscape.length }); }; Lexer.prototype.makeDelimitedLiteral = function(body, options) { var regex; if (options == null) { options = {}; } if (body === '' && options.delimiter === '/') { body = '(?:)'; } regex = RegExp("(\\\\\\\\)|(\\\\0(?=[1-7]))|\\\\?(" + options.delimiter + ")|\\\\?(?:(\\n)|(\\r)|(\\u2028)|(\\u2029))|(\\\\.)", "g"); body = body.replace(regex, function(match, backslash, nul, delimiter, lf, cr, ls, ps, other) { switch (false) { case !backslash: if (options.double) { return backslash + backslash; } else { return backslash; } case !nul: return '\\x00'; case !delimiter: return "\\" + delimiter; case !lf: return '\\n'; case !cr: return '\\r'; case !ls: return '\\u2028'; case !ps: return '\\u2029'; case !other: if (options.double) { return "\\" + other; } else { return other; } } }); return "" + options.delimiter + body + options.delimiter; }; Lexer.prototype.error = function(message, options) { var first_column, first_line, location, ref2, ref3, ref4; if (options == null) { options = {}; } 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, first_column: first_column, last_column: first_column + ((ref4 = options.length) != null ? ref4 : 1) - 1 }); return throwSyntaxError(message, location); }; return Lexer; })(); JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'yield', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super']; COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when']; COFFEE_ALIAS_MAP = { and: '&&', or: '||', is: '==', isnt: '!=', not: '!', yes: 'true', no: 'false', on: 'true', off: 'false' }; COFFEE_ALIASES = (function() { var results; results = []; for (key in COFFEE_ALIAS_MAP) { results.push(key); } return results; })(); COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES); RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', 'implements', 'interface', 'package', 'private', 'protected', 'public', 'static']; STRICT_PROSCRIBED = ['arguments', 'eval', 'yield*']; JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED); exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED); exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED; BOM = 65279; IDENTIFIER = /^(?!\d)((?:(?!\s)[$\w\x7f-\uffff])+)([^\n\S]*:(?!:))?/; NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i; OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>*\/%])\2=?|\?(\.|::)|\.{2,3})/; WHITESPACE = /^[^\n\S]+/; COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|###$)|^(?:\s*#(?!##[^#]).*)+/; CODE = /^[-=]>/; MULTI_DENT = /^(?:\n[^\n\S]*)+/; JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/; STRING_START = /^(?:'''|"""|'|")/; STRING_SINGLE = /^(?:[^\\']|\\[\s\S])*/; STRING_DOUBLE = /^(?:[^\\"#]|\\[\s\S]|\#(?!\{))*/; HEREDOC_SINGLE = /^(?:[^\\']|\\[\s\S]|'(?!''))*/; HEREDOC_DOUBLE = /^(?:[^\\"#]|\\[\s\S]|"(?!"")|\#(?!\{))*/; STRING_OMIT = /((?:\\\\)+)|\\[^\S\n]*\n\s*/g; SIMPLE_STRING_OMIT = /\s*\n\s*/g; HEREDOC_INDENT = /\n+([^\n\S]*)(?=\S)/g; REGEX = /^\/(?!\/)((?:[^[\/\n\\]|\\[^\n]|\[(?:\\[^\n]|[^\]\n\\])*\])*)(\/)?/; REGEX_FLAGS = /^\w*/; VALID_FLAGS = /^(?!.*(.).*\1)[imgy]*$/; HEREGEX = /^(?:[^\\\/#]|\\[\s\S]|\/(?!\/\/)|\#(?!\{))*/; HEREGEX_OMIT = /((?:\\\\)+)|\\(\s)|\s+(?:#.*)?/g; REGEX_ILLEGAL = /^(\/|\/{3}\s*)(\*)/; POSSIBLY_DIVISION = /^\/=?\s/; HERECOMMENT_ILLEGAL = /\*\//; LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/; INVALID_ESCAPE = /((?:^|[^\\])(?:\\\\)*)\\(?:(0[0-7]|[1-7])|(x(?![\da-fA-F]{2}).{0,2})|(u(?![\da-fA-F]{4}).{0,4}))/; LEADING_BLANK_LINE = /^[^\n\S]*\n/; TRAILING_BLANK_LINE = /\n[^\n\S]*$/; TRAILING_SPACES = /\s+$/; COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|=', '**=', '//=', '%%=']; UNARY = ['NEW', 'TYPEOF', 'DELETE', 'DO']; UNARY_MATH = ['!', '~']; LOGIC = ['&&', '||', '&', '|', '^']; SHIFT = ['<<', '>>', '>>>']; COMPARE = ['==', '!=', '<', '>', '<=', '>=']; MATH = ['*', '/', '%', '//', '%%']; RELATION = ['IN', 'OF', 'INSTANCEOF']; BOOL = ['TRUE', 'FALSE']; CALLABLE = ['IDENTIFIER', ')', ']', '?', '@', 'THIS', 'SUPER']; INDEXABLE = CALLABLE.concat(['NUMBER', 'STRING', 'STRING_END', 'REGEX', 'REGEX_END', 'BOOL', 'NULL', 'UNDEFINED', '}', '::']); NOT_REGEX = INDEXABLE.concat(['++', '--']); LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR']; INDENTABLE_CLOSERS = [')', '}', ']']; }).call(this); 1.9.3~dfsg/lib/coffee-script/cake.js0000644000000000000000000000566512531364553016051 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var CoffeeScript, cakefileDirectory, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks; fs = require('fs'); path = require('path'); helpers = require('./helpers'); optparse = require('./optparse'); CoffeeScript = require('./coffee-script'); CoffeeScript.register(); tasks = {}; options = {}; switches = []; oparse = null; helpers.extend(global, { task: function(name, description, action) { var ref; if (!action) { ref = [description, action], action = ref[0], description = ref[1]; } return tasks[name] = { name: name, description: description, action: action }; }, option: function(letter, flag, description) { return switches.push([letter, flag, description]); }, invoke: function(name) { if (!tasks[name]) { missingTask(name); } return tasks[name].action(options); } }); exports.run = function() { var arg, args, e, i, len, ref, results; global.__originalDirname = fs.realpathSync('.'); process.chdir(cakefileDirectory(__originalDirname)); args = process.argv.slice(2); CoffeeScript.run(fs.readFileSync('Cakefile').toString(), { filename: 'Cakefile' }); oparse = new optparse.OptionParser(switches); if (!args.length) { return printTasks(); } try { options = oparse.parse(args); } catch (_error) { e = _error; return fatalError("" + e); } ref = options["arguments"]; results = []; for (i = 0, len = ref.length; i < len; i++) { arg = ref[i]; results.push(invoke(arg)); } return results; }; printTasks = function() { var cakefilePath, desc, name, relative, spaces, task; relative = path.relative || path.resolve; cakefilePath = path.join(relative(__originalDirname, process.cwd()), 'Cakefile'); console.log(cakefilePath + " defines the following tasks:\n"); for (name in tasks) { task = tasks[name]; spaces = 20 - name.length; spaces = spaces > 0 ? Array(spaces + 1).join(' ') : ''; desc = task.description ? "# " + task.description : ''; console.log("cake " + name + spaces + " " + desc); } if (switches.length) { return console.log(oparse.help()); } }; fatalError = function(message) { console.error(message + '\n'); console.log('To see a list of all tasks/options, run "cake"'); return process.exit(1); }; missingTask = function(task) { return fatalError("No such task: " + task); }; cakefileDirectory = function(dir) { var parent; if (fs.existsSync(path.join(dir, 'Cakefile'))) { return dir; } parent = path.normalize(path.join(dir, '..')); if (parent !== dir) { return cakefileDirectory(parent); } throw new Error("Cakefile not found in " + (process.cwd())); }; }).call(this); 1.9.3~dfsg/lib/coffee-script/parser.js0000755000000000000000000023254012531364553016437 0ustar rootroot/* parser generated by jison 0.4.15 */ /* Returns a Parser object of the following structure: Parser: { yy: {} } Parser.prototype: { yy: {}, trace: function(), symbols_: {associative list: name ==> number}, terminals_: {associative list: number ==> name}, productions_: [...], performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$), table: [...], defaultActions: {...}, parseError: function(str, hash), parse: function(input), lexer: { EOF: 1, parseError: function(str, hash), setInput: function(input), input: function(), unput: function(str), more: function(), less: function(n), pastInput: function(), upcomingInput: function(), showPosition: function(), test_match: function(regex_match_array, rule_index), next: function(), lex: function(), begin: function(condition), popState: function(), _currentRules: function(), topState: function(), pushState: function(condition), options: { ranges: boolean (optional: true ==> token location info will include a .range[] member) flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match) backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code) }, performAction: function(yy, yy_, $avoiding_name_collisions, YY_START), rules: [...], conditions: {associative list: name ==> set}, } } token location info (@$, _$, etc.): { first_line: n, last_line: n, first_column: n, last_column: n, range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based) } the parseError function receives a 'hash' object with these members for lexer and parser errors: { text: (matched text) token: (the produced terminal token, if any) line: (yylineno) } while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: { loc: (yylloc) expected: (string describing the set of expected tokens) recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error) } */ var parser = (function(){ var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,20],$V1=[1,75],$V2=[1,71],$V3=[1,76],$V4=[1,77],$V5=[1,73],$V6=[1,74],$V7=[1,50],$V8=[1,52],$V9=[1,53],$Va=[1,54],$Vb=[1,55],$Vc=[1,45],$Vd=[1,46],$Ve=[1,27],$Vf=[1,60],$Vg=[1,61],$Vh=[1,70],$Vi=[1,43],$Vj=[1,26],$Vk=[1,58],$Vl=[1,59],$Vm=[1,57],$Vn=[1,38],$Vo=[1,44],$Vp=[1,56],$Vq=[1,65],$Vr=[1,66],$Vs=[1,67],$Vt=[1,68],$Vu=[1,42],$Vv=[1,64],$Vw=[1,29],$Vx=[1,30],$Vy=[1,31],$Vz=[1,32],$VA=[1,33],$VB=[1,34],$VC=[1,35],$VD=[1,78],$VE=[1,6,26,34,108],$VF=[1,88],$VG=[1,81],$VH=[1,80],$VI=[1,79],$VJ=[1,82],$VK=[1,83],$VL=[1,84],$VM=[1,85],$VN=[1,86],$VO=[1,87],$VP=[1,91],$VQ=[1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,117,132,135,136,141,142,143,144,145,146,147],$VR=[1,97],$VS=[1,98],$VT=[1,99],$VU=[1,100],$VV=[1,102],$VW=[1,103],$VX=[1,96],$VY=[2,112],$VZ=[1,6,25,26,34,55,60,63,72,73,74,75,77,79,80,84,90,91,92,97,99,108,110,111,112,116,117,132,135,136,141,142,143,144,145,146,147],$V_=[2,79],$V$=[1,108],$V01=[2,58],$V11=[1,112],$V21=[1,117],$V31=[1,118],$V41=[1,120],$V51=[1,6,25,26,34,46,55,60,63,72,73,74,75,77,79,80,84,90,91,92,97,99,108,110,111,112,116,117,132,135,136,141,142,143,144,145,146,147],$V61=[2,76],$V71=[1,6,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,117,132,135,136,141,142,143,144,145,146,147],$V81=[1,155],$V91=[1,157],$Va1=[1,152],$Vb1=[1,6,25,26,34,46,55,60,63,72,73,74,75,77,79,80,84,86,90,91,92,97,99,108,110,111,112,116,117,132,135,136,139,140,141,142,143,144,145,146,147,148],$Vc1=[2,95],$Vd1=[1,6,25,26,34,49,55,60,63,72,73,74,75,77,79,80,84,90,91,92,97,99,108,110,111,112,116,117,132,135,136,141,142,143,144,145,146,147],$Ve1=[1,6,25,26,34,46,49,55,60,63,72,73,74,75,77,79,80,84,86,90,91,92,97,99,108,110,111,112,116,117,123,124,132,135,136,139,140,141,142,143,144,145,146,147,148],$Vf1=[1,206],$Vg1=[1,205],$Vh1=[1,6,25,26,34,38,55,60,63,72,73,74,75,77,79,80,84,90,91,92,97,99,108,110,111,112,116,117,132,135,136,141,142,143,144,145,146,147],$Vi1=[2,56],$Vj1=[1,216],$Vk1=[6,25,26,55,60],$Vl1=[6,25,26,46,55,60,63],$Vm1=[1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,117,132,135,136,142,144,145,146,147],$Vn1=[1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,117,132],$Vo1=[72,73,74,75,77,80,90,91],$Vp1=[1,235],$Vq1=[2,133],$Vr1=[1,6,25,26,34,46,55,60,63,72,73,74,75,77,79,80,84,90,91,92,97,99,108,110,111,112,116,117,123,124,132,135,136,141,142,143,144,145,146,147],$Vs1=[1,244],$Vt1=[6,25,26,60,92,97],$Vu1=[1,6,25,26,34,55,60,63,79,84,92,97,99,108,117,132],$Vv1=[1,6,25,26,34,55,60,63,79,84,92,97,99,108,111,117,132],$Vw1=[123,124],$Vx1=[60,123,124],$Vy1=[1,255],$Vz1=[6,25,26,60,84],$VA1=[6,25,26,49,60,84],$VB1=[1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,117,132,135,136,144,145,146,147],$VC1=[11,28,30,32,33,36,37,40,41,42,43,44,51,52,53,57,58,79,82,85,89,94,95,96,102,106,107,110,112,114,116,125,131,133,134,135,136,137,139,140],$VD1=[2,122],$VE1=[6,25,26],$VF1=[2,57],$VG1=[1,268],$VH1=[1,269],$VI1=[1,6,25,26,34,55,60,63,79,84,92,97,99,104,105,108,110,111,112,116,117,127,129,132,135,136,141,142,143,144,145,146,147],$VJ1=[26,127,129],$VK1=[1,6,26,34,55,60,63,79,84,92,97,99,108,111,117,132],$VL1=[2,71],$VM1=[1,291],$VN1=[1,292],$VO1=[1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,117,127,132,135,136,141,142,143,144,145,146,147],$VP1=[1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,112,116,117,132],$VQ1=[1,303],$VR1=[1,304],$VS1=[6,25,26,60],$VT1=[1,6,25,26,34,55,60,63,79,84,92,97,99,104,108,110,111,112,116,117,132,135,136,141,142,143,144,145,146,147],$VU1=[25,60]; var parser = {trace: function trace() { }, yy: {}, symbols_: {"error":2,"Root":3,"Body":4,"Line":5,"TERMINATOR":6,"Expression":7,"Statement":8,"Return":9,"Comment":10,"STATEMENT":11,"Value":12,"Invocation":13,"Code":14,"Operation":15,"Assign":16,"If":17,"Try":18,"While":19,"For":20,"Switch":21,"Class":22,"Throw":23,"Block":24,"INDENT":25,"OUTDENT":26,"Identifier":27,"IDENTIFIER":28,"AlphaNumeric":29,"NUMBER":30,"String":31,"STRING":32,"STRING_START":33,"STRING_END":34,"Regex":35,"REGEX":36,"REGEX_START":37,"REGEX_END":38,"Literal":39,"JS":40,"DEBUGGER":41,"UNDEFINED":42,"NULL":43,"BOOL":44,"Assignable":45,"=":46,"AssignObj":47,"ObjAssignable":48,":":49,"ThisProperty":50,"RETURN":51,"HERECOMMENT":52,"PARAM_START":53,"ParamList":54,"PARAM_END":55,"FuncGlyph":56,"->":57,"=>":58,"OptComma":59,",":60,"Param":61,"ParamVar":62,"...":63,"Array":64,"Object":65,"Splat":66,"SimpleAssignable":67,"Accessor":68,"Parenthetical":69,"Range":70,"This":71,".":72,"?.":73,"::":74,"?::":75,"Index":76,"INDEX_START":77,"IndexValue":78,"INDEX_END":79,"INDEX_SOAK":80,"Slice":81,"{":82,"AssignList":83,"}":84,"CLASS":85,"EXTENDS":86,"OptFuncExist":87,"Arguments":88,"SUPER":89,"FUNC_EXIST":90,"CALL_START":91,"CALL_END":92,"ArgList":93,"THIS":94,"@":95,"[":96,"]":97,"RangeDots":98,"..":99,"Arg":100,"SimpleArgs":101,"TRY":102,"Catch":103,"FINALLY":104,"CATCH":105,"THROW":106,"(":107,")":108,"WhileSource":109,"WHILE":110,"WHEN":111,"UNTIL":112,"Loop":113,"LOOP":114,"ForBody":115,"FOR":116,"BY":117,"ForStart":118,"ForSource":119,"ForVariables":120,"OWN":121,"ForValue":122,"FORIN":123,"FOROF":124,"SWITCH":125,"Whens":126,"ELSE":127,"When":128,"LEADING_WHEN":129,"IfBlock":130,"IF":131,"POST_IF":132,"UNARY":133,"UNARY_MATH":134,"-":135,"+":136,"YIELD":137,"FROM":138,"--":139,"++":140,"?":141,"MATH":142,"**":143,"SHIFT":144,"COMPARE":145,"LOGIC":146,"RELATION":147,"COMPOUND_ASSIGN":148,"$accept":0,"$end":1}, terminals_: {2:"error",6:"TERMINATOR",11:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",32:"STRING",33:"STRING_START",34:"STRING_END",36:"REGEX",37:"REGEX_START",38:"REGEX_END",40:"JS",41:"DEBUGGER",42:"UNDEFINED",43:"NULL",44:"BOOL",46:"=",49:":",51:"RETURN",52:"HERECOMMENT",53:"PARAM_START",55:"PARAM_END",57:"->",58:"=>",60:",",63:"...",72:".",73:"?.",74:"::",75:"?::",77:"INDEX_START",79:"INDEX_END",80:"INDEX_SOAK",82:"{",84:"}",85:"CLASS",86:"EXTENDS",89:"SUPER",90:"FUNC_EXIST",91:"CALL_START",92:"CALL_END",94:"THIS",95:"@",96:"[",97:"]",99:"..",102:"TRY",104:"FINALLY",105:"CATCH",106:"THROW",107:"(",108:")",110:"WHILE",111:"WHEN",112:"UNTIL",114:"LOOP",116:"FOR",117:"BY",121:"OWN",123:"FORIN",124:"FOROF",125:"SWITCH",127:"ELSE",129:"LEADING_WHEN",131:"IF",132:"POST_IF",133:"UNARY",134:"UNARY_MATH",135:"-",136:"+",137:"YIELD",138:"FROM",139:"--",140:"++",141:"?",142:"MATH",143:"**",144:"SHIFT",145:"COMPARE",146:"LOGIC",147:"RELATION",148:"COMPOUND_ASSIGN"}, productions_: [0,[3,0],[3,1],[4,1],[4,3],[4,2],[5,1],[5,1],[8,1],[8,1],[8,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[24,2],[24,3],[27,1],[29,1],[29,1],[31,1],[31,3],[35,1],[35,3],[39,1],[39,1],[39,1],[39,1],[39,1],[39,1],[39,1],[16,3],[16,4],[16,5],[47,1],[47,3],[47,5],[47,1],[48,1],[48,1],[48,1],[9,2],[9,1],[10,1],[14,5],[14,2],[56,1],[56,1],[59,0],[59,1],[54,0],[54,1],[54,3],[54,4],[54,6],[61,1],[61,2],[61,3],[61,1],[62,1],[62,1],[62,1],[62,1],[66,2],[67,1],[67,2],[67,2],[67,1],[45,1],[45,1],[45,1],[12,1],[12,1],[12,1],[12,1],[12,1],[68,2],[68,2],[68,2],[68,2],[68,1],[68,1],[76,3],[76,2],[78,1],[78,1],[65,4],[83,0],[83,1],[83,3],[83,4],[83,6],[22,1],[22,2],[22,3],[22,4],[22,2],[22,3],[22,4],[22,5],[13,3],[13,3],[13,1],[13,2],[87,0],[87,1],[88,2],[88,4],[71,1],[71,1],[50,2],[64,2],[64,4],[98,1],[98,1],[70,5],[81,3],[81,2],[81,2],[81,1],[93,1],[93,3],[93,4],[93,4],[93,6],[100,1],[100,1],[100,1],[101,1],[101,3],[18,2],[18,3],[18,4],[18,5],[103,3],[103,3],[103,2],[23,2],[69,3],[69,5],[109,2],[109,4],[109,2],[109,4],[19,2],[19,2],[19,2],[19,1],[113,2],[113,2],[20,2],[20,2],[20,2],[115,2],[115,4],[115,2],[118,2],[118,3],[122,1],[122,1],[122,1],[122,1],[120,1],[120,3],[119,2],[119,2],[119,4],[119,4],[119,4],[119,6],[119,6],[21,5],[21,7],[21,4],[21,6],[126,1],[126,2],[128,3],[128,4],[130,3],[130,5],[17,1],[17,3],[17,3],[17,3],[15,2],[15,2],[15,2],[15,2],[15,2],[15,2],[15,3],[15,2],[15,2],[15,2],[15,2],[15,2],[15,3],[15,3],[15,3],[15,3],[15,3],[15,3],[15,3],[15,3],[15,3],[15,5],[15,4],[15,3]], performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) { /* this == yyval */ var $0 = $$.length - 1; switch (yystate) { case 1: return this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Block); break; case 2: return this.$ = $$[$0]; break; case 3: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(yy.Block.wrap([$$[$0]])); break; case 4: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])($$[$0-2].push($$[$0])); break; case 5: this.$ = $$[$0-1]; break; case 6: case 7: case 8: case 9: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 27: case 32: case 34: case 45: case 46: case 47: case 48: case 56: case 57: case 67: case 68: case 69: case 70: case 75: case 76: case 79: case 83: case 89: case 133: case 134: case 136: case 166: case 167: case 183: case 189: this.$ = $$[$0]; break; case 10: case 25: case 26: case 28: case 30: case 33: case 35: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Literal($$[$0])); break; case 23: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Block); break; case 24: case 31: case 90: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])($$[$0-1]); break; case 29: case 146: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Parens($$[$0-1])); break; case 36: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Undefined); break; case 37: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Null); break; case 38: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Bool($$[$0])); break; case 39: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Assign($$[$0-2], $$[$0])); break; case 40: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])(new yy.Assign($$[$0-3], $$[$0])); break; case 41: this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Assign($$[$0-4], $$[$0-1])); break; case 42: case 72: case 77: case 78: case 80: case 81: case 82: case 168: case 169: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Value($$[$0])); break; case 43: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Assign(yy.addLocationDataFn(_$[$0-2])(new yy.Value($$[$0-2])), $$[$0], 'object')); break; case 44: this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Assign(yy.addLocationDataFn(_$[$0-4])(new yy.Value($$[$0-4])), $$[$0-1], 'object')); break; case 49: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Return($$[$0])); break; case 50: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Return); break; case 51: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Comment($$[$0])); break; case 52: this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Code($$[$0-3], $$[$0], $$[$0-1])); break; case 53: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Code([], $$[$0], $$[$0-1])); break; case 54: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])('func'); break; case 55: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])('boundfunc'); break; case 58: case 95: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])([]); break; case 59: case 96: case 128: case 170: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])([$$[$0]]); break; case 60: case 97: case 129: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])($$[$0-2].concat($$[$0])); break; case 61: case 98: case 130: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])($$[$0-3].concat($$[$0])); break; case 62: case 99: case 132: this.$ = yy.addLocationDataFn(_$[$0-5], _$[$0])($$[$0-5].concat($$[$0-2])); break; case 63: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Param($$[$0])); break; case 64: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Param($$[$0-1], null, true)); break; case 65: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Param($$[$0-2], $$[$0])); break; case 66: case 135: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Expansion); break; case 71: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Splat($$[$0-1])); break; case 73: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])($$[$0-1].add($$[$0])); break; case 74: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Value($$[$0-1], [].concat($$[$0]))); break; case 84: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Access($$[$0])); break; case 85: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Access($$[$0], 'soak')); break; case 86: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])([yy.addLocationDataFn(_$[$0-1])(new yy.Access(new yy.Literal('prototype'))), yy.addLocationDataFn(_$[$0])(new yy.Access($$[$0]))]); break; case 87: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])([yy.addLocationDataFn(_$[$0-1])(new yy.Access(new yy.Literal('prototype'), 'soak')), yy.addLocationDataFn(_$[$0])(new yy.Access($$[$0]))]); break; case 88: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Access(new yy.Literal('prototype'))); break; case 91: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(yy.extend($$[$0], { soak: true })); break; case 92: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Index($$[$0])); break; case 93: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Slice($$[$0])); break; case 94: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])(new yy.Obj($$[$0-2], $$[$0-3].generated)); break; case 100: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Class); break; case 101: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Class(null, null, $$[$0])); break; case 102: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Class(null, $$[$0])); break; case 103: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])(new yy.Class(null, $$[$0-1], $$[$0])); break; case 104: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Class($$[$0])); break; case 105: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Class($$[$0-1], null, $$[$0])); break; case 106: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])(new yy.Class($$[$0-2], $$[$0])); break; case 107: this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Class($$[$0-3], $$[$0-1], $$[$0])); break; case 108: case 109: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Call($$[$0-2], $$[$0], $$[$0-1])); break; case 110: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Call('super', [new yy.Splat(new yy.Literal('arguments'))])); break; case 111: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Call('super', $$[$0])); break; case 112: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(false); break; case 113: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(true); break; case 114: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])([]); break; case 115: case 131: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])($$[$0-2]); break; case 116: case 117: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Value(new yy.Literal('this'))); break; case 118: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Value(yy.addLocationDataFn(_$[$0-1])(new yy.Literal('this')), [yy.addLocationDataFn(_$[$0])(new yy.Access($$[$0]))], 'this')); break; case 119: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Arr([])); break; case 120: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])(new yy.Arr($$[$0-2])); break; case 121: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])('inclusive'); break; case 122: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])('exclusive'); break; case 123: this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Range($$[$0-3], $$[$0-1], $$[$0-2])); break; case 124: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Range($$[$0-2], $$[$0], $$[$0-1])); break; case 125: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Range($$[$0-1], null, $$[$0])); break; case 126: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Range(null, $$[$0], $$[$0-1])); break; case 127: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])(new yy.Range(null, null, $$[$0])); break; case 137: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])([].concat($$[$0-2], $$[$0])); break; case 138: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Try($$[$0])); break; case 139: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Try($$[$0-1], $$[$0][0], $$[$0][1])); break; case 140: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])(new yy.Try($$[$0-2], null, null, $$[$0])); break; case 141: this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Try($$[$0-3], $$[$0-2][0], $$[$0-2][1], $$[$0])); break; case 142: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])([$$[$0-1], $$[$0]]); break; case 143: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])([yy.addLocationDataFn(_$[$0-1])(new yy.Value($$[$0-1])), $$[$0]]); break; case 144: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])([null, $$[$0]]); break; case 145: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Throw($$[$0])); break; case 147: this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Parens($$[$0-2])); break; case 148: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.While($$[$0])); break; case 149: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])(new yy.While($$[$0-2], { guard: $$[$0] })); break; case 150: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.While($$[$0], { invert: true })); break; case 151: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])(new yy.While($$[$0-2], { invert: true, guard: $$[$0] })); break; case 152: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])($$[$0-1].addBody($$[$0])); break; case 153: case 154: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])($$[$0].addBody(yy.addLocationDataFn(_$[$0-1])(yy.Block.wrap([$$[$0-1]])))); break; case 155: this.$ = yy.addLocationDataFn(_$[$0], _$[$0])($$[$0]); break; case 156: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.While(yy.addLocationDataFn(_$[$0-1])(new yy.Literal('true'))).addBody($$[$0])); break; case 157: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.While(yy.addLocationDataFn(_$[$0-1])(new yy.Literal('true'))).addBody(yy.addLocationDataFn(_$[$0])(yy.Block.wrap([$$[$0]])))); break; case 158: case 159: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.For($$[$0-1], $$[$0])); break; case 160: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.For($$[$0], $$[$0-1])); break; case 161: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])({ source: yy.addLocationDataFn(_$[$0])(new yy.Value($$[$0])) }); break; case 162: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])({ source: yy.addLocationDataFn(_$[$0-2])(new yy.Value($$[$0-2])), step: $$[$0] }); break; case 163: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])((function () { $$[$0].own = $$[$0-1].own; $$[$0].name = $$[$0-1][0]; $$[$0].index = $$[$0-1][1]; return $$[$0]; }())); break; case 164: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])($$[$0]); break; case 165: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])((function () { $$[$0].own = true; return $$[$0]; }())); break; case 171: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])([$$[$0-2], $$[$0]]); break; case 172: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])({ source: $$[$0] }); break; case 173: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])({ source: $$[$0], object: true }); break; case 174: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])({ source: $$[$0-2], guard: $$[$0] }); break; case 175: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])({ source: $$[$0-2], guard: $$[$0], object: true }); break; case 176: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])({ source: $$[$0-2], step: $$[$0] }); break; case 177: this.$ = yy.addLocationDataFn(_$[$0-5], _$[$0])({ source: $$[$0-4], guard: $$[$0-2], step: $$[$0] }); break; case 178: this.$ = yy.addLocationDataFn(_$[$0-5], _$[$0])({ source: $$[$0-4], step: $$[$0-2], guard: $$[$0] }); break; case 179: this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Switch($$[$0-3], $$[$0-1])); break; case 180: this.$ = yy.addLocationDataFn(_$[$0-6], _$[$0])(new yy.Switch($$[$0-5], $$[$0-3], $$[$0-1])); break; case 181: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])(new yy.Switch(null, $$[$0-1])); break; case 182: this.$ = yy.addLocationDataFn(_$[$0-5], _$[$0])(new yy.Switch(null, $$[$0-3], $$[$0-1])); break; case 184: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])($$[$0-1].concat($$[$0])); break; case 185: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])([[$$[$0-1], $$[$0]]]); break; case 186: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])([[$$[$0-2], $$[$0-1]]]); break; case 187: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.If($$[$0-1], $$[$0], { type: $$[$0-2] })); break; case 188: this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])($$[$0-4].addElse(yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.If($$[$0-1], $$[$0], { type: $$[$0-2] })))); break; case 190: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])($$[$0-2].addElse($$[$0])); break; case 191: case 192: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.If($$[$0], yy.addLocationDataFn(_$[$0-2])(yy.Block.wrap([$$[$0-2]])), { type: $$[$0-1], statement: true })); break; case 193: case 194: case 197: case 198: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op($$[$0-1], $$[$0])); break; case 195: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op('-', $$[$0])); break; case 196: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op('+', $$[$0])); break; case 199: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Op($$[$0-2].concat($$[$0-1]), $$[$0])); break; case 200: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op('--', $$[$0])); break; case 201: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op('++', $$[$0])); break; case 202: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op('--', $$[$0-1], null, true)); break; case 203: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Op('++', $$[$0-1], null, true)); break; case 204: this.$ = yy.addLocationDataFn(_$[$0-1], _$[$0])(new yy.Existence($$[$0-1])); break; case 205: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Op('+', $$[$0-2], $$[$0])); break; case 206: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Op('-', $$[$0-2], $$[$0])); break; case 207: case 208: case 209: case 210: case 211: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Op($$[$0-1], $$[$0-2], $$[$0])); break; case 212: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])((function () { if ($$[$0-1].charAt(0) === '!') { return new yy.Op($$[$0-1].slice(1), $$[$0-2], $$[$0]).invert(); } else { return new yy.Op($$[$0-1], $$[$0-2], $$[$0]); } }())); break; case 213: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Assign($$[$0-2], $$[$0], $$[$0-1])); break; case 214: this.$ = yy.addLocationDataFn(_$[$0-4], _$[$0])(new yy.Assign($$[$0-4], $$[$0-1], $$[$0-3])); break; case 215: this.$ = yy.addLocationDataFn(_$[$0-3], _$[$0])(new yy.Assign($$[$0-3], $$[$0], $$[$0-2])); break; case 216: this.$ = yy.addLocationDataFn(_$[$0-2], _$[$0])(new yy.Extends($$[$0-2], $$[$0])); break; } }, table: [{1:[2,1],3:1,4:2,5:3,7:4,8:5,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{1:[3]},{1:[2,2],6:$VD},o($VE,[2,3]),o($VE,[2,6],{118:69,109:89,115:90,110:$Vq,112:$Vr,116:$Vt,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($VE,[2,7],{118:69,109:92,115:93,110:$Vq,112:$Vr,116:$Vt,132:$VP}),o($VQ,[2,11],{87:94,68:95,76:101,72:$VR,73:$VS,74:$VT,75:$VU,77:$VV,80:$VW,90:$VX,91:$VY}),o($VQ,[2,12],{76:101,87:104,68:105,72:$VR,73:$VS,74:$VT,75:$VU,77:$VV,80:$VW,90:$VX,91:$VY}),o($VQ,[2,13]),o($VQ,[2,14]),o($VQ,[2,15]),o($VQ,[2,16]),o($VQ,[2,17]),o($VQ,[2,18]),o($VQ,[2,19]),o($VQ,[2,20]),o($VQ,[2,21]),o($VQ,[2,22]),o($VQ,[2,8]),o($VQ,[2,9]),o($VQ,[2,10]),o($VZ,$V_,{46:[1,106]}),o($VZ,[2,80]),o($VZ,[2,81]),o($VZ,[2,82]),o($VZ,[2,83]),o([1,6,25,26,34,38,55,60,63,72,73,74,75,77,79,80,84,90,92,97,99,108,110,111,112,116,117,132,135,136,141,142,143,144,145,146,147],[2,110],{88:107,91:$V$}),o([6,25,55,60],$V01,{54:109,61:110,62:111,27:113,50:114,64:115,65:116,28:$V1,63:$V11,82:$Vh,95:$V21,96:$V31}),{24:119,25:$V41},{7:121,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:123,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:124,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:125,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:127,8:126,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,138:[1,128],139:$VB,140:$VC},{12:130,13:131,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:132,50:63,64:47,65:48,67:129,69:23,70:24,71:25,82:$Vh,89:$Vj,94:$Vk,95:$Vl,96:$Vm,107:$Vp},{12:130,13:131,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:132,50:63,64:47,65:48,67:133,69:23,70:24,71:25,82:$Vh,89:$Vj,94:$Vk,95:$Vl,96:$Vm,107:$Vp},o($V51,$V61,{86:[1,137],139:[1,134],140:[1,135],148:[1,136]}),o($VQ,[2,189],{127:[1,138]}),{24:139,25:$V41},{24:140,25:$V41},o($VQ,[2,155]),{24:141,25:$V41},{7:142,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,143],27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($V71,[2,100],{39:22,69:23,70:24,71:25,64:47,65:48,29:49,35:51,27:62,50:63,31:72,12:130,13:131,45:132,24:144,67:146,25:$V41,28:$V1,30:$V2,32:$V3,33:$V4,36:$V5,37:$V6,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,82:$Vh,86:[1,145],89:$Vj,94:$Vk,95:$Vl,96:$Vm,107:$Vp}),{7:147,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o([1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,117,132,141,142,143,144,145,146,147],[2,50],{12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,9:18,10:19,45:21,39:22,69:23,70:24,71:25,56:28,67:36,130:37,109:39,113:40,115:41,64:47,65:48,29:49,35:51,27:62,50:63,118:69,31:72,8:122,7:148,11:$V0,28:$V1,30:$V2,32:$V3,33:$V4,36:$V5,37:$V6,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,51:$Vc,52:$Vd,53:$Ve,57:$Vf,58:$Vg,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,114:$Vs,125:$Vu,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC}),o($VQ,[2,51]),o($V51,[2,77]),o($V51,[2,78]),o($VZ,[2,32]),o($VZ,[2,33]),o($VZ,[2,34]),o($VZ,[2,35]),o($VZ,[2,36]),o($VZ,[2,37]),o($VZ,[2,38]),{4:149,5:3,7:4,8:5,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,150],27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:151,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:$V81,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,63:$V91,64:47,65:48,66:156,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,93:153,94:$Vk,95:$Vl,96:$Vm,97:$Va1,100:154,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($VZ,[2,116]),o($VZ,[2,117],{27:158,28:$V1}),{25:[2,54]},{25:[2,55]},o($Vb1,[2,72]),o($Vb1,[2,75]),{7:159,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:160,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:161,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:163,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:162,25:$V41,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{27:168,28:$V1,50:169,64:170,65:171,70:164,82:$Vh,95:$V21,96:$Vm,120:165,121:[1,166],122:167},{119:172,123:[1,173],124:[1,174]},o([6,25,60,84],$Vc1,{31:72,83:175,47:176,48:177,10:178,27:179,29:180,50:181,28:$V1,30:$V2,32:$V3,33:$V4,52:$Vd,95:$V21}),o($Vd1,[2,26]),o($Vd1,[2,27]),o($VZ,[2,30]),{12:130,13:182,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:132,50:63,64:47,65:48,67:183,69:23,70:24,71:25,82:$Vh,89:$Vj,94:$Vk,95:$Vl,96:$Vm,107:$Vp},o($Ve1,[2,25]),o($Vd1,[2,28]),{4:184,5:3,7:4,8:5,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($VE,[2,5],{7:4,8:5,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,9:18,10:19,45:21,39:22,69:23,70:24,71:25,56:28,67:36,130:37,109:39,113:40,115:41,64:47,65:48,29:49,35:51,27:62,50:63,118:69,31:72,5:185,11:$V0,28:$V1,30:$V2,32:$V3,33:$V4,36:$V5,37:$V6,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,51:$Vc,52:$Vd,53:$Ve,57:$Vf,58:$Vg,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,110:$Vq,112:$Vr,114:$Vs,116:$Vt,125:$Vu,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC}),o($VQ,[2,204]),{7:186,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:187,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:188,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:189,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:190,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:191,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:192,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:193,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:194,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($VQ,[2,154]),o($VQ,[2,159]),{7:195,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($VQ,[2,153]),o($VQ,[2,158]),{88:196,91:$V$},o($Vb1,[2,73]),{91:[2,113]},{27:197,28:$V1},{27:198,28:$V1},o($Vb1,[2,88],{27:199,28:$V1}),{27:200,28:$V1},o($Vb1,[2,89]),{7:202,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,63:$Vf1,64:47,65:48,67:36,69:23,70:24,71:25,78:201,81:203,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,98:204,99:$Vg1,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{76:207,77:$VV,80:$VW},{88:208,91:$V$},o($Vb1,[2,74]),{6:[1,210],7:209,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,211],27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($Vh1,[2,111]),{7:214,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:$V81,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,63:$V91,64:47,65:48,66:156,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,92:[1,212],93:213,94:$Vk,95:$Vl,96:$Vm,100:154,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o([6,25],$Vi1,{59:217,55:[1,215],60:$Vj1}),o($Vk1,[2,59]),o($Vk1,[2,63],{46:[1,219],63:[1,218]}),o($Vk1,[2,66]),o($Vl1,[2,67]),o($Vl1,[2,68]),o($Vl1,[2,69]),o($Vl1,[2,70]),{27:158,28:$V1},{7:214,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:$V81,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,63:$V91,64:47,65:48,66:156,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,93:153,94:$Vk,95:$Vl,96:$Vm,97:$Va1,100:154,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($VQ,[2,53]),{4:221,5:3,7:4,8:5,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,26:[1,220],27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o([1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,117,132,135,136,142,143,144,145,146,147],[2,193],{118:69,109:89,115:90,141:$VI}),{109:92,110:$Vq,112:$Vr,115:93,116:$Vt,118:69,132:$VP},o($Vm1,[2,194],{118:69,109:89,115:90,141:$VI,143:$VK}),o($Vm1,[2,195],{118:69,109:89,115:90,141:$VI,143:$VK}),o($Vm1,[2,196],{118:69,109:89,115:90,141:$VI,143:$VK}),o($VQ,[2,197],{118:69,109:92,115:93}),o($Vn1,[2,198],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),{7:222,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($VQ,[2,200],{72:$V61,73:$V61,74:$V61,75:$V61,77:$V61,80:$V61,90:$V61,91:$V61}),{68:95,72:$VR,73:$VS,74:$VT,75:$VU,76:101,77:$VV,80:$VW,87:94,90:$VX,91:$VY},{68:105,72:$VR,73:$VS,74:$VT,75:$VU,76:101,77:$VV,80:$VW,87:104,90:$VX,91:$VY},o($Vo1,$V_),o($VQ,[2,201],{72:$V61,73:$V61,74:$V61,75:$V61,77:$V61,80:$V61,90:$V61,91:$V61}),o($VQ,[2,202]),o($VQ,[2,203]),{6:[1,225],7:223,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,224],27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:226,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{24:227,25:$V41,131:[1,228]},o($VQ,[2,138],{103:229,104:[1,230],105:[1,231]}),o($VQ,[2,152]),o($VQ,[2,160]),{25:[1,232],109:89,110:$Vq,112:$Vr,115:90,116:$Vt,118:69,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO},{126:233,128:234,129:$Vp1},o($VQ,[2,101]),{7:236,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($V71,[2,104],{24:237,25:$V41,72:$V61,73:$V61,74:$V61,75:$V61,77:$V61,80:$V61,90:$V61,91:$V61,86:[1,238]}),o($Vn1,[2,145],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($Vn1,[2,49],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),{6:$VD,108:[1,239]},{4:240,5:3,7:4,8:5,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o([6,25,60,97],$Vq1,{118:69,109:89,115:90,98:241,63:[1,242],99:$Vg1,110:$Vq,112:$Vr,116:$Vt,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($Vr1,[2,119]),o([6,25,97],$Vi1,{59:243,60:$Vs1}),o($Vt1,[2,128]),{7:214,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:$V81,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,63:$V91,64:47,65:48,66:156,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,93:245,94:$Vk,95:$Vl,96:$Vm,100:154,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($Vt1,[2,134]),o($Vt1,[2,135]),o($Ve1,[2,118]),{24:246,25:$V41,109:89,110:$Vq,112:$Vr,115:90,116:$Vt,118:69,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO},o($Vu1,[2,148],{118:69,109:89,115:90,110:$Vq,111:[1,247],112:$Vr,116:$Vt,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($Vu1,[2,150],{118:69,109:89,115:90,110:$Vq,111:[1,248],112:$Vr,116:$Vt,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($VQ,[2,156]),o($Vv1,[2,157],{118:69,109:89,115:90,110:$Vq,112:$Vr,116:$Vt,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o([1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,132,135,136,141,142,143,144,145,146,147],[2,161],{117:[1,249]}),o($Vw1,[2,164]),{27:168,28:$V1,50:169,64:170,65:171,82:$Vh,95:$V21,96:$V31,120:250,122:167},o($Vw1,[2,170],{60:[1,251]}),o($Vx1,[2,166]),o($Vx1,[2,167]),o($Vx1,[2,168]),o($Vx1,[2,169]),o($VQ,[2,163]),{7:252,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:253,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o([6,25,84],$Vi1,{59:254,60:$Vy1}),o($Vz1,[2,96]),o($Vz1,[2,42],{49:[1,256]}),o($Vz1,[2,45]),o($VA1,[2,46]),o($VA1,[2,47]),o($VA1,[2,48]),{38:[1,257],68:105,72:$VR,73:$VS,74:$VT,75:$VU,76:101,77:$VV,80:$VW,87:104,90:$VX,91:$VY},o($Vo1,$V61),{6:$VD,34:[1,258]},o($VE,[2,4]),o($VB1,[2,205],{118:69,109:89,115:90,141:$VI,142:$VJ,143:$VK}),o($VB1,[2,206],{118:69,109:89,115:90,141:$VI,142:$VJ,143:$VK}),o($Vm1,[2,207],{118:69,109:89,115:90,141:$VI,143:$VK}),o($Vm1,[2,208],{118:69,109:89,115:90,141:$VI,143:$VK}),o([1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,117,132,144,145,146,147],[2,209],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK}),o([1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,117,132,145,146],[2,210],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,147:$VO}),o([1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,117,132,146],[2,211],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,147:$VO}),o([1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,117,132,145,146,147],[2,212],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL}),o($Vv1,[2,192],{118:69,109:89,115:90,110:$Vq,112:$Vr,116:$Vt,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($Vv1,[2,191],{118:69,109:89,115:90,110:$Vq,112:$Vr,116:$Vt,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($Vh1,[2,108]),o($Vb1,[2,84]),o($Vb1,[2,85]),o($Vb1,[2,86]),o($Vb1,[2,87]),{79:[1,259]},{63:$Vf1,79:[2,92],98:260,99:$Vg1,109:89,110:$Vq,112:$Vr,115:90,116:$Vt,118:69,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO},{79:[2,93]},{7:261,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,79:[2,127],82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($VC1,[2,121]),o($VC1,$VD1),o($Vb1,[2,91]),o($Vh1,[2,109]),o($Vn1,[2,39],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),{7:262,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:263,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($Vh1,[2,114]),o([6,25,92],$Vi1,{59:264,60:$Vs1}),o($Vt1,$Vq1,{118:69,109:89,115:90,63:[1,265],110:$Vq,112:$Vr,116:$Vt,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),{56:266,57:$Vf,58:$Vg},o($VE1,$VF1,{62:111,27:113,50:114,64:115,65:116,61:267,28:$V1,63:$V11,82:$Vh,95:$V21,96:$V31}),{6:$VG1,25:$VH1},o($Vk1,[2,64]),{7:270,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($VI1,[2,23]),{6:$VD,26:[1,271]},o($Vn1,[2,199],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($Vn1,[2,213],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),{7:272,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:273,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($Vn1,[2,216],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($VQ,[2,190]),{7:274,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($VQ,[2,139],{104:[1,275]}),{24:276,25:$V41},{24:279,25:$V41,27:277,28:$V1,65:278,82:$Vh},{126:280,128:234,129:$Vp1},{26:[1,281],127:[1,282],128:283,129:$Vp1},o($VJ1,[2,183]),{7:285,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,101:284,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($VK1,[2,102],{118:69,109:89,115:90,24:286,25:$V41,110:$Vq,112:$Vr,116:$Vt,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($VQ,[2,105]),{7:287,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($VZ,[2,146]),{6:$VD,26:[1,288]},{7:289,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o([11,28,30,32,33,36,37,40,41,42,43,44,51,52,53,57,58,82,85,89,94,95,96,102,106,107,110,112,114,116,125,131,133,134,135,136,137,139,140],$VD1,{6:$VL1,25:$VL1,60:$VL1,97:$VL1}),{6:$VM1,25:$VN1,97:[1,290]},o([6,25,26,92,97],$VF1,{12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,9:18,10:19,45:21,39:22,69:23,70:24,71:25,56:28,67:36,130:37,109:39,113:40,115:41,64:47,65:48,29:49,35:51,27:62,50:63,118:69,31:72,8:122,66:156,7:214,100:293,11:$V0,28:$V1,30:$V2,32:$V3,33:$V4,36:$V5,37:$V6,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,51:$Vc,52:$Vd,53:$Ve,57:$Vf,58:$Vg,63:$V91,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,110:$Vq,112:$Vr,114:$Vs,116:$Vt,125:$Vu,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC}),o($VE1,$Vi1,{59:294,60:$Vs1}),o($VO1,[2,187]),{7:295,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:296,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:297,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($Vw1,[2,165]),{27:168,28:$V1,50:169,64:170,65:171,82:$Vh,95:$V21,96:$V31,122:298},o([1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,112,116,132],[2,172],{118:69,109:89,115:90,111:[1,299],117:[1,300],135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($VP1,[2,173],{118:69,109:89,115:90,111:[1,301],135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),{6:$VQ1,25:$VR1,84:[1,302]},o([6,25,26,84],$VF1,{31:72,48:177,10:178,27:179,29:180,50:181,47:305,28:$V1,30:$V2,32:$V3,33:$V4,52:$Vd,95:$V21}),{7:306,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,307],27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($VZ,[2,31]),o($Vd1,[2,29]),o($Vb1,[2,90]),{7:308,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,79:[2,125],82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{79:[2,126],109:89,110:$Vq,112:$Vr,115:90,116:$Vt,118:69,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO},o($Vn1,[2,40],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),{26:[1,309],109:89,110:$Vq,112:$Vr,115:90,116:$Vt,118:69,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO},{6:$VM1,25:$VN1,92:[1,310]},o($Vt1,$VL1),{24:311,25:$V41},o($Vk1,[2,60]),{27:113,28:$V1,50:114,61:312,62:111,63:$V11,64:115,65:116,82:$Vh,95:$V21,96:$V31},o($VS1,$V01,{61:110,62:111,27:113,50:114,64:115,65:116,54:313,28:$V1,63:$V11,82:$Vh,95:$V21,96:$V31}),o($Vk1,[2,65],{118:69,109:89,115:90,110:$Vq,112:$Vr,116:$Vt,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($VI1,[2,24]),{26:[1,314],109:89,110:$Vq,112:$Vr,115:90,116:$Vt,118:69,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO},o($Vn1,[2,215],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),{24:315,25:$V41,109:89,110:$Vq,112:$Vr,115:90,116:$Vt,118:69,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO},{24:316,25:$V41},o($VQ,[2,140]),{24:317,25:$V41},{24:318,25:$V41},o($VT1,[2,144]),{26:[1,319],127:[1,320],128:283,129:$Vp1},o($VQ,[2,181]),{24:321,25:$V41},o($VJ1,[2,184]),{24:322,25:$V41,60:[1,323]},o($VU1,[2,136],{118:69,109:89,115:90,110:$Vq,112:$Vr,116:$Vt,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($VQ,[2,103]),o($VK1,[2,106],{118:69,109:89,115:90,24:324,25:$V41,110:$Vq,112:$Vr,116:$Vt,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),{108:[1,325]},{97:[1,326],109:89,110:$Vq,112:$Vr,115:90,116:$Vt,118:69,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO},o($Vr1,[2,120]),{7:214,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,63:$V91,64:47,65:48,66:156,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,100:327,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:214,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:$V81,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,63:$V91,64:47,65:48,66:156,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,93:328,94:$Vk,95:$Vl,96:$Vm,100:154,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($Vt1,[2,129]),{6:$VM1,25:$VN1,26:[1,329]},o($Vv1,[2,149],{118:69,109:89,115:90,110:$Vq,112:$Vr,116:$Vt,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($Vv1,[2,151],{118:69,109:89,115:90,110:$Vq,112:$Vr,116:$Vt,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($Vv1,[2,162],{118:69,109:89,115:90,110:$Vq,112:$Vr,116:$Vt,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($Vw1,[2,171]),{7:330,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:331,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:332,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($Vr1,[2,94]),{10:178,27:179,28:$V1,29:180,30:$V2,31:72,32:$V3,33:$V4,47:333,48:177,50:181,52:$Vd,95:$V21},o($VS1,$Vc1,{31:72,47:176,48:177,10:178,27:179,29:180,50:181,83:334,28:$V1,30:$V2,32:$V3,33:$V4,52:$Vd,95:$V21}),o($Vz1,[2,97]),o($Vz1,[2,43],{118:69,109:89,115:90,110:$Vq,112:$Vr,116:$Vt,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),{7:335,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{79:[2,124],109:89,110:$Vq,112:$Vr,115:90,116:$Vt,118:69,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO},o($VQ,[2,41]),o($Vh1,[2,115]),o($VQ,[2,52]),o($Vk1,[2,61]),o($VE1,$Vi1,{59:336,60:$Vj1}),o($VQ,[2,214]),o($VO1,[2,188]),o($VQ,[2,141]),o($VT1,[2,142]),o($VT1,[2,143]),o($VQ,[2,179]),{24:337,25:$V41},{26:[1,338]},o($VJ1,[2,185],{6:[1,339]}),{7:340,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},o($VQ,[2,107]),o($VZ,[2,147]),o($VZ,[2,123]),o($Vt1,[2,130]),o($VE1,$Vi1,{59:341,60:$Vs1}),o($Vt1,[2,131]),o([1,6,25,26,34,55,60,63,79,84,92,97,99,108,110,111,112,116,132],[2,174],{118:69,109:89,115:90,117:[1,342],135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($VP1,[2,176],{118:69,109:89,115:90,111:[1,343],135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($Vn1,[2,175],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($Vz1,[2,98]),o($VE1,$Vi1,{59:344,60:$Vy1}),{26:[1,345],109:89,110:$Vq,112:$Vr,115:90,116:$Vt,118:69,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO},{6:$VG1,25:$VH1,26:[1,346]},{26:[1,347]},o($VQ,[2,182]),o($VJ1,[2,186]),o($VU1,[2,137],{118:69,109:89,115:90,110:$Vq,112:$Vr,116:$Vt,132:$VF,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),{6:$VM1,25:$VN1,26:[1,348]},{7:349,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{7:350,8:122,9:18,10:19,11:$V0,12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:62,28:$V1,29:49,30:$V2,31:72,32:$V3,33:$V4,35:51,36:$V5,37:$V6,39:22,40:$V7,41:$V8,42:$V9,43:$Va,44:$Vb,45:21,50:63,51:$Vc,52:$Vd,53:$Ve,56:28,57:$Vf,58:$Vg,64:47,65:48,67:36,69:23,70:24,71:25,82:$Vh,85:$Vi,89:$Vj,94:$Vk,95:$Vl,96:$Vm,102:$Vn,106:$Vo,107:$Vp,109:39,110:$Vq,112:$Vr,113:40,114:$Vs,115:41,116:$Vt,118:69,125:$Vu,130:37,131:$Vv,133:$Vw,134:$Vx,135:$Vy,136:$Vz,137:$VA,139:$VB,140:$VC},{6:$VQ1,25:$VR1,26:[1,351]},o($Vz1,[2,44]),o($Vk1,[2,62]),o($VQ,[2,180]),o($Vt1,[2,132]),o($Vn1,[2,177],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($Vn1,[2,178],{118:69,109:89,115:90,135:$VG,136:$VH,141:$VI,142:$VJ,143:$VK,144:$VL,145:$VM,146:$VN,147:$VO}),o($Vz1,[2,99])], defaultActions: {60:[2,54],61:[2,55],96:[2,113],203:[2,93]}, parseError: function parseError(str, hash) { if (hash.recoverable) { this.trace(str); } else { throw new Error(str); } }, parse: function parse(input) { var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; var args = lstack.slice.call(arguments, 1); var lexer = Object.create(this.lexer); var sharedState = { yy: {} }; for (var k in this.yy) { if (Object.prototype.hasOwnProperty.call(this.yy, k)) { sharedState.yy[k] = this.yy[k]; } } lexer.setInput(input, sharedState.yy); sharedState.yy.lexer = lexer; sharedState.yy.parser = this; if (typeof lexer.yylloc == 'undefined') { lexer.yylloc = {}; } var yyloc = lexer.yylloc; lstack.push(yyloc); var ranges = lexer.options && lexer.options.ranges; if (typeof sharedState.yy.parseError === 'function') { this.parseError = sharedState.yy.parseError; } else { this.parseError = Object.getPrototypeOf(this).parseError; } function popStack(n) { stack.length = stack.length - 2 * n; vstack.length = vstack.length - n; lstack.length = lstack.length - n; } _token_stack: function lex() { var token; token = lexer.lex() || EOF; if (typeof token !== 'number') { token = self.symbols_[token] || token; } return token; } var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; while (true) { state = stack[stack.length - 1]; if (this.defaultActions[state]) { action = this.defaultActions[state]; } else { if (symbol === null || typeof symbol == 'undefined') { symbol = lex(); } action = table[state] && table[state][symbol]; } if (typeof action === 'undefined' || !action.length || !action[0]) { var errStr = ''; expected = []; for (p in table[state]) { if (this.terminals_[p] && p > TERROR) { expected.push('\'' + this.terminals_[p] + '\''); } } if (lexer.showPosition) { errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''; } else { errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\''); } this.parseError(errStr, { text: lexer.match, token: this.terminals_[symbol] || symbol, line: lexer.yylineno, loc: yyloc, expected: expected }); } if (action[0] instanceof Array && action.length > 1) { throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol); } switch (action[0]) { case 1: stack.push(symbol); vstack.push(lexer.yytext); lstack.push(lexer.yylloc); stack.push(action[1]); symbol = null; if (!preErrorSymbol) { yyleng = lexer.yyleng; yytext = lexer.yytext; yylineno = lexer.yylineno; yyloc = lexer.yylloc; if (recovering > 0) { recovering--; } } else { symbol = preErrorSymbol; preErrorSymbol = null; } break; case 2: len = this.productions_[action[1]][1]; yyval.$ = vstack[vstack.length - len]; yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column }; if (ranges) { yyval._$.range = [ lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1] ]; } r = this.performAction.apply(yyval, [ yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack ].concat(args)); if (typeof r !== 'undefined') { return r; } if (len) { stack = stack.slice(0, -1 * len * 2); vstack = vstack.slice(0, -1 * len); lstack = lstack.slice(0, -1 * len); } stack.push(this.productions_[action[1]][0]); vstack.push(yyval.$); lstack.push(yyval._$); newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; stack.push(newState); break; case 3: return true; } } return true; }}; function Parser () { this.yy = {}; } Parser.prototype = parser;parser.Parser = Parser; return new Parser; })(); if (typeof require !== 'undefined' && typeof exports !== 'undefined') { exports.parser = parser; exports.Parser = parser.Parser; exports.parse = function () { return parser.parse.apply(parser, arguments); }; exports.main = function commonjsMain(args) { if (!args[1]) { console.log('Usage: '+args[0]+' FILE'); process.exit(1); } var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8"); return exports.parser.parse(source); }; if (typeof module !== 'undefined' && require.main === module) { exports.main(process.argv.slice(1)); } }1.9.3~dfsg/lib/coffee-script/register.js0000644000000000000000000000350012531364553016754 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var CoffeeScript, Module, binary, child_process, ext, findExtension, fork, helpers, i, len, loadFile, path, ref; CoffeeScript = require('./coffee-script'); child_process = require('child_process'); helpers = require('./helpers'); path = require('path'); loadFile = function(module, filename) { var answer; answer = CoffeeScript._compileFile(filename, false); return module._compile(answer, filename); }; if (require.extensions) { ref = CoffeeScript.FILE_EXTENSIONS; for (i = 0, len = ref.length; i < len; i++) { ext = ref[i]; require.extensions[ext] = loadFile; } Module = require('module'); findExtension = function(filename) { var curExtension, extensions; extensions = path.basename(filename).split('.'); if (extensions[0] === '') { extensions.shift(); } while (extensions.shift()) { curExtension = '.' + extensions.join('.'); if (Module._extensions[curExtension]) { return curExtension; } } return '.js'; }; Module.prototype.load = function(filename) { var extension; this.filename = filename; this.paths = Module._nodeModulePaths(path.dirname(filename)); extension = findExtension(filename); Module._extensions[extension](this, filename); return this.loaded = true; }; } if (child_process) { fork = child_process.fork; binary = require.resolve('../../bin/coffee'); child_process.fork = function(path, args, options) { if (helpers.isCoffee(path)) { if (!Array.isArray(args)) { options = args || {}; args = []; } args = [path].concat(args); path = binary; } return fork(path, args, options); }; } }).call(this); 1.9.3~dfsg/lib/coffee-script/nodes.js0000644000000000000000000032443012531364553016250 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var Access, Arr, Assign, Base, Block, Call, Class, Code, CodeFragment, Comment, Existence, Expansion, Extends, For, HEXNUM, IDENTIFIER, IS_REGEX, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, NEGATE, NO, NUMBER, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, STRICT_PROSCRIBED, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, addLocationDataFn, compact, del, ends, extend, flatten, fragmentsToText, isComplexOrAssignable, isLiteralArguments, isLiteralThis, locationDataToString, merge, multident, parseNum, ref1, ref2, some, starts, throwSyntaxError, unfoldSoak, utility, extend1 = 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, 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; }, slice = [].slice; Error.stackTraceLimit = Infinity; Scope = require('./scope').Scope; ref1 = require('./lexer'), RESERVED = ref1.RESERVED, STRICT_PROSCRIBED = ref1.STRICT_PROSCRIBED; ref2 = require('./helpers'), compact = ref2.compact, flatten = ref2.flatten, extend = ref2.extend, merge = ref2.merge, del = ref2.del, starts = ref2.starts, ends = ref2.ends, some = ref2.some, addLocationDataFn = ref2.addLocationDataFn, locationDataToString = ref2.locationDataToString, throwSyntaxError = ref2.throwSyntaxError; exports.extend = extend; exports.addLocationDataFn = addLocationDataFn; YES = function() { return true; }; NO = function() { return false; }; THIS = function() { return this; }; NEGATE = function() { this.negated = !this.negated; return this; }; exports.CodeFragment = CodeFragment = (function() { function CodeFragment(parent, code) { var ref3; this.code = "" + code; this.locationData = parent != null ? parent.locationData : void 0; this.type = (parent != null ? (ref3 = parent.constructor) != null ? ref3.name : void 0 : void 0) || 'unknown'; } CodeFragment.prototype.toString = function() { return "" + this.code + (this.locationData ? ": " + locationDataToString(this.locationData) : ''); }; return CodeFragment; })(); fragmentsToText = function(fragments) { var fragment; return ((function() { var j, len1, results; results = []; for (j = 0, len1 = fragments.length; j < len1; j++) { fragment = fragments[j]; results.push(fragment.code); } return results; })()).join(''); }; exports.Base = Base = (function() { function Base() {} Base.prototype.compile = function(o, lvl) { return fragmentsToText(this.compileToFragments(o, lvl)); }; Base.prototype.compileToFragments = function(o, lvl) { var node; o = extend({}, o); if (lvl) { o.level = lvl; } node = this.unfoldSoak(o) || this; node.tab = o.indent; if (o.level === LEVEL_TOP || !node.isStatement(o)) { return node.compileNode(o); } else { return node.compileClosure(o); } }; Base.prototype.compileClosure = function(o) { var args, argumentsNode, func, jumpNode, meth, parts, ref3; if (jumpNode = this.jumps()) { jumpNode.error('cannot use a pure statement in an expression'); } o.sharedScope = true; func = new Code([], Block.wrap([this])); args = []; if ((argumentsNode = this.contains(isLiteralArguments)) || this.contains(isLiteralThis)) { args = [new Literal('this')]; if (argumentsNode) { meth = 'apply'; args.push(new Literal('arguments')); } else { meth = 'call'; } func = new Value(func, [new Access(new Literal(meth))]); } parts = (new Call(func, args)).compileNode(o); if (func.isGenerator || ((ref3 = func.base) != null ? ref3.isGenerator : void 0)) { parts.unshift(this.makeCode("(yield* ")); parts.push(this.makeCode(")")); } return parts; }; Base.prototype.cache = function(o, level, isComplex) { var complex, ref, sub; complex = isComplex != null ? isComplex(this) : this.isComplex(); if (complex) { ref = new Literal(o.scope.freeVariable('ref')); sub = new Assign(ref, this); if (level) { return [sub.compileToFragments(o, level), [this.makeCode(ref.value)]]; } else { return [sub, ref]; } } else { ref = level ? this.compileToFragments(o, level) : this; return [ref, ref]; } }; Base.prototype.cacheToCodeFragments = function(cacheValues) { return [fragmentsToText(cacheValues[0]), fragmentsToText(cacheValues[1])]; }; Base.prototype.makeReturn = function(res) { var me; me = this.unwrapAll(); if (res) { return new Call(new Literal(res + ".push"), [me]); } else { return new Return(me); } }; Base.prototype.contains = function(pred) { var node; node = void 0; this.traverseChildren(false, function(n) { if (pred(n)) { node = n; return false; } }); return node; }; Base.prototype.lastNonComment = function(list) { var i; i = list.length; while (i--) { if (!(list[i] instanceof Comment)) { return list[i]; } } return null; }; Base.prototype.toString = function(idt, name) { var tree; if (idt == null) { idt = ''; } if (name == null) { name = this.constructor.name; } tree = '\n' + idt + name; if (this.soak) { tree += '?'; } this.eachChild(function(node) { return tree += node.toString(idt + TAB); }); return tree; }; Base.prototype.eachChild = function(func) { var attr, child, j, k, len1, len2, ref3, ref4; if (!this.children) { return this; } ref3 = this.children; for (j = 0, len1 = ref3.length; j < len1; j++) { attr = ref3[j]; if (this[attr]) { ref4 = flatten([this[attr]]); for (k = 0, len2 = ref4.length; k < len2; k++) { child = ref4[k]; if (func(child) === false) { return this; } } } } return this; }; Base.prototype.traverseChildren = function(crossScope, func) { return this.eachChild(function(child) { var recur; recur = func(child); if (recur !== false) { return child.traverseChildren(crossScope, func); } }); }; Base.prototype.invert = function() { return new Op('!', this); }; Base.prototype.unwrapAll = function() { var node; node = this; while (node !== (node = node.unwrap())) { continue; } return node; }; Base.prototype.children = []; Base.prototype.isStatement = NO; Base.prototype.jumps = NO; Base.prototype.isComplex = YES; Base.prototype.isChainable = NO; Base.prototype.isAssignable = NO; Base.prototype.unwrap = THIS; Base.prototype.unfoldSoak = NO; Base.prototype.assigns = NO; Base.prototype.updateLocationDataIfMissing = function(locationData) { if (this.locationData) { return this; } this.locationData = locationData; return this.eachChild(function(child) { return child.updateLocationDataIfMissing(locationData); }); }; Base.prototype.error = function(message) { return throwSyntaxError(message, this.locationData); }; Base.prototype.makeCode = function(code) { return new CodeFragment(this, code); }; Base.prototype.wrapInBraces = function(fragments) { return [].concat(this.makeCode('('), fragments, this.makeCode(')')); }; Base.prototype.joinFragmentArrays = function(fragmentsList, joinStr) { var answer, fragments, i, j, len1; answer = []; for (i = j = 0, len1 = fragmentsList.length; j < len1; i = ++j) { fragments = fragmentsList[i]; if (i) { answer.push(this.makeCode(joinStr)); } answer = answer.concat(fragments); } return answer; }; return Base; })(); exports.Block = Block = (function(superClass1) { extend1(Block, superClass1); function Block(nodes) { this.expressions = compact(flatten(nodes || [])); } Block.prototype.children = ['expressions']; Block.prototype.push = function(node) { this.expressions.push(node); return this; }; Block.prototype.pop = function() { return this.expressions.pop(); }; Block.prototype.unshift = function(node) { this.expressions.unshift(node); return this; }; Block.prototype.unwrap = function() { if (this.expressions.length === 1) { return this.expressions[0]; } else { return this; } }; Block.prototype.isEmpty = function() { return !this.expressions.length; }; Block.prototype.isStatement = function(o) { var exp, j, len1, ref3; ref3 = this.expressions; for (j = 0, len1 = ref3.length; j < len1; j++) { exp = ref3[j]; if (exp.isStatement(o)) { return true; } } return false; }; Block.prototype.jumps = function(o) { var exp, j, jumpNode, len1, ref3; ref3 = this.expressions; for (j = 0, len1 = ref3.length; j < len1; j++) { exp = ref3[j]; if (jumpNode = exp.jumps(o)) { return jumpNode; } } }; Block.prototype.makeReturn = function(res) { var expr, len; len = this.expressions.length; while (len--) { expr = this.expressions[len]; if (!(expr instanceof Comment)) { this.expressions[len] = expr.makeReturn(res); if (expr instanceof Return && !expr.expression) { this.expressions.splice(len, 1); } break; } } return this; }; Block.prototype.compileToFragments = function(o, level) { if (o == null) { o = {}; } if (o.scope) { return Block.__super__.compileToFragments.call(this, o, level); } else { return this.compileRoot(o); } }; Block.prototype.compileNode = function(o) { var answer, compiledNodes, fragments, index, j, len1, node, ref3, top; this.tab = o.indent; top = o.level === LEVEL_TOP; compiledNodes = []; ref3 = this.expressions; for (index = j = 0, len1 = ref3.length; j < len1; index = ++j) { node = ref3[index]; node = node.unwrapAll(); node = node.unfoldSoak(o) || node; if (node instanceof Block) { compiledNodes.push(node.compileNode(o)); } else if (top) { node.front = true; fragments = node.compileToFragments(o); if (!node.isStatement(o)) { fragments.unshift(this.makeCode("" + this.tab)); fragments.push(this.makeCode(";")); } compiledNodes.push(fragments); } else { compiledNodes.push(node.compileToFragments(o, LEVEL_LIST)); } } if (top) { if (this.spaced) { return [].concat(this.joinFragmentArrays(compiledNodes, '\n\n'), this.makeCode("\n")); } else { return this.joinFragmentArrays(compiledNodes, '\n'); } } if (compiledNodes.length) { answer = this.joinFragmentArrays(compiledNodes, ', '); } else { answer = [this.makeCode("void 0")]; } if (compiledNodes.length > 1 && o.level >= LEVEL_LIST) { return this.wrapInBraces(answer); } else { return answer; } }; Block.prototype.compileRoot = function(o) { var exp, fragments, i, j, len1, name, prelude, preludeExps, ref3, ref4, rest; o.indent = o.bare ? '' : TAB; o.level = LEVEL_TOP; this.spaced = true; o.scope = new Scope(null, this, null, (ref3 = o.referencedVars) != null ? ref3 : []); ref4 = o.locals || []; for (j = 0, len1 = ref4.length; j < len1; j++) { name = ref4[j]; o.scope.parameter(name); } prelude = []; if (!o.bare) { preludeExps = (function() { var k, len2, ref5, results; ref5 = this.expressions; results = []; for (i = k = 0, len2 = ref5.length; k < len2; i = ++k) { exp = ref5[i]; if (!(exp.unwrap() instanceof Comment)) { break; } results.push(exp); } return results; }).call(this); rest = this.expressions.slice(preludeExps.length); this.expressions = preludeExps; if (preludeExps.length) { prelude = this.compileNode(merge(o, { indent: '' })); prelude.push(this.makeCode("\n")); } this.expressions = rest; } fragments = this.compileWithDeclarations(o); if (o.bare) { return fragments; } return [].concat(prelude, this.makeCode("(function() {\n"), fragments, this.makeCode("\n}).call(this);\n")); }; Block.prototype.compileWithDeclarations = function(o) { var assigns, declars, exp, fragments, i, j, len1, post, ref3, ref4, ref5, rest, scope, spaced; fragments = []; post = []; ref3 = this.expressions; for (i = j = 0, len1 = ref3.length; j < len1; i = ++j) { exp = ref3[i]; exp = exp.unwrap(); if (!(exp instanceof Comment || exp instanceof Literal)) { break; } } o = merge(o, { level: LEVEL_TOP }); if (i) { rest = this.expressions.splice(i, 9e9); ref4 = [this.spaced, false], spaced = ref4[0], this.spaced = ref4[1]; ref5 = [this.compileNode(o), spaced], fragments = ref5[0], this.spaced = ref5[1]; this.expressions = rest; } post = this.compileNode(o); scope = o.scope; if (scope.expressions === this) { declars = o.scope.hasDeclarations(); assigns = scope.hasAssignments; if (declars || assigns) { if (i) { fragments.push(this.makeCode('\n')); } fragments.push(this.makeCode(this.tab + "var ")); if (declars) { fragments.push(this.makeCode(scope.declaredVariables().join(', '))); } if (assigns) { if (declars) { fragments.push(this.makeCode(",\n" + (this.tab + TAB))); } fragments.push(this.makeCode(scope.assignedVariables().join(",\n" + (this.tab + TAB)))); } fragments.push(this.makeCode(";\n" + (this.spaced ? '\n' : ''))); } else if (fragments.length && post.length) { fragments.push(this.makeCode("\n")); } } return fragments.concat(post); }; Block.wrap = function(nodes) { if (nodes.length === 1 && nodes[0] instanceof Block) { return nodes[0]; } return new Block(nodes); }; return Block; })(Base); exports.Literal = Literal = (function(superClass1) { extend1(Literal, superClass1); function Literal(value1) { this.value = value1; } Literal.prototype.makeReturn = function() { if (this.isStatement()) { return this; } else { return Literal.__super__.makeReturn.apply(this, arguments); } }; Literal.prototype.isAssignable = function() { return IDENTIFIER.test(this.value); }; Literal.prototype.isStatement = function() { var ref3; return (ref3 = this.value) === 'break' || ref3 === 'continue' || ref3 === 'debugger'; }; Literal.prototype.isComplex = NO; Literal.prototype.assigns = function(name) { return name === this.value; }; Literal.prototype.jumps = function(o) { if (this.value === 'break' && !((o != null ? o.loop : void 0) || (o != null ? o.block : void 0))) { return this; } if (this.value === 'continue' && !(o != null ? o.loop : void 0)) { return this; } }; Literal.prototype.compileNode = function(o) { var answer, code, ref3; code = this.value === 'this' ? ((ref3 = o.scope.method) != null ? ref3.bound : void 0) ? o.scope.method.context : this.value : this.value.reserved ? "\"" + this.value + "\"" : this.value; answer = this.isStatement() ? "" + this.tab + code + ";" : code; return [this.makeCode(answer)]; }; Literal.prototype.toString = function() { return ' "' + this.value + '"'; }; return Literal; })(Base); exports.Undefined = (function(superClass1) { extend1(Undefined, superClass1); function Undefined() { return Undefined.__super__.constructor.apply(this, arguments); } Undefined.prototype.isAssignable = NO; Undefined.prototype.isComplex = NO; Undefined.prototype.compileNode = function(o) { return [this.makeCode(o.level >= LEVEL_ACCESS ? '(void 0)' : 'void 0')]; }; return Undefined; })(Base); exports.Null = (function(superClass1) { extend1(Null, superClass1); function Null() { return Null.__super__.constructor.apply(this, arguments); } Null.prototype.isAssignable = NO; Null.prototype.isComplex = NO; Null.prototype.compileNode = function() { return [this.makeCode("null")]; }; return Null; })(Base); exports.Bool = (function(superClass1) { extend1(Bool, superClass1); Bool.prototype.isAssignable = NO; Bool.prototype.isComplex = NO; Bool.prototype.compileNode = function() { return [this.makeCode(this.val)]; }; function Bool(val1) { this.val = val1; } return Bool; })(Base); exports.Return = Return = (function(superClass1) { extend1(Return, superClass1); function Return(expression) { this.expression = expression; } Return.prototype.children = ['expression']; Return.prototype.isStatement = YES; Return.prototype.makeReturn = THIS; Return.prototype.jumps = THIS; Return.prototype.compileToFragments = function(o, level) { var expr, ref3; expr = (ref3 = this.expression) != null ? ref3.makeReturn() : void 0; if (expr && !(expr instanceof Return)) { return expr.compileToFragments(o, level); } else { return Return.__super__.compileToFragments.call(this, o, level); } }; Return.prototype.compileNode = function(o) { var answer, exprIsYieldReturn, ref3; answer = []; exprIsYieldReturn = (ref3 = this.expression) != null ? typeof ref3.isYieldReturn === "function" ? ref3.isYieldReturn() : void 0 : void 0; if (!exprIsYieldReturn) { answer.push(this.makeCode(this.tab + ("return" + (this.expression ? " " : "")))); } if (this.expression) { answer = answer.concat(this.expression.compileToFragments(o, LEVEL_PAREN)); } if (!exprIsYieldReturn) { answer.push(this.makeCode(";")); } return answer; }; return Return; })(Base); exports.Value = Value = (function(superClass1) { extend1(Value, superClass1); function Value(base, props, tag) { if (!props && base instanceof Value) { return base; } this.base = base; this.properties = props || []; if (tag) { this[tag] = true; } return this; } Value.prototype.children = ['base', 'properties']; Value.prototype.add = function(props) { this.properties = this.properties.concat(props); return this; }; Value.prototype.hasProperties = function() { return !!this.properties.length; }; Value.prototype.bareLiteral = function(type) { return !this.properties.length && this.base instanceof type; }; Value.prototype.isArray = function() { return this.bareLiteral(Arr); }; Value.prototype.isRange = function() { return this.bareLiteral(Range); }; Value.prototype.isComplex = function() { return this.hasProperties() || this.base.isComplex(); }; Value.prototype.isAssignable = function() { return this.hasProperties() || this.base.isAssignable(); }; Value.prototype.isSimpleNumber = function() { return this.bareLiteral(Literal) && SIMPLENUM.test(this.base.value); }; Value.prototype.isString = function() { return this.bareLiteral(Literal) && IS_STRING.test(this.base.value); }; Value.prototype.isRegex = function() { return this.bareLiteral(Literal) && IS_REGEX.test(this.base.value); }; Value.prototype.isAtomic = function() { var j, len1, node, ref3; ref3 = this.properties.concat(this.base); for (j = 0, len1 = ref3.length; j < len1; j++) { node = ref3[j]; if (node.soak || node instanceof Call) { return false; } } return true; }; Value.prototype.isNotCallable = function() { return this.isSimpleNumber() || this.isString() || this.isRegex() || this.isArray() || this.isRange() || this.isSplice() || this.isObject(); }; Value.prototype.isStatement = function(o) { return !this.properties.length && this.base.isStatement(o); }; Value.prototype.assigns = function(name) { return !this.properties.length && this.base.assigns(name); }; Value.prototype.jumps = function(o) { return !this.properties.length && this.base.jumps(o); }; Value.prototype.isObject = function(onlyGenerated) { if (this.properties.length) { return false; } return (this.base instanceof Obj) && (!onlyGenerated || this.base.generated); }; Value.prototype.isSplice = function() { var lastProp, ref3; ref3 = this.properties, lastProp = ref3[ref3.length - 1]; return lastProp instanceof Slice; }; Value.prototype.looksStatic = function(className) { var ref3; return this.base.value === className && this.properties.length === 1 && ((ref3 = this.properties[0].name) != null ? ref3.value : void 0) !== 'prototype'; }; Value.prototype.unwrap = function() { if (this.properties.length) { return this; } else { return this.base; } }; Value.prototype.cacheReference = function(o) { var base, bref, name, nref, ref3; ref3 = this.properties, name = ref3[ref3.length - 1]; if (this.properties.length < 2 && !this.base.isComplex() && !(name != null ? name.isComplex() : void 0)) { return [this, this]; } base = new Value(this.base, this.properties.slice(0, -1)); if (base.isComplex()) { bref = new Literal(o.scope.freeVariable('base')); base = new Value(new Parens(new Assign(bref, base))); } if (!name) { return [base, bref]; } if (name.isComplex()) { nref = new Literal(o.scope.freeVariable('name')); name = new Index(new Assign(nref, name.index)); nref = new Index(nref); } return [base.add(name), new Value(bref || base.base, [nref || name])]; }; Value.prototype.compileNode = function(o) { var fragments, j, len1, prop, props; this.base.front = this.front; props = this.properties; fragments = this.base.compileToFragments(o, (props.length ? LEVEL_ACCESS : null)); if ((this.base instanceof Parens || props.length) && SIMPLENUM.test(fragmentsToText(fragments))) { fragments.push(this.makeCode('.')); } for (j = 0, len1 = props.length; j < len1; j++) { prop = props[j]; fragments.push.apply(fragments, prop.compileToFragments(o)); } return fragments; }; Value.prototype.unfoldSoak = function(o) { return this.unfoldedSoak != null ? this.unfoldedSoak : this.unfoldedSoak = (function(_this) { return function() { var fst, i, ifn, j, len1, prop, ref, ref3, ref4, snd; if (ifn = _this.base.unfoldSoak(o)) { (ref3 = ifn.body.properties).push.apply(ref3, _this.properties); return ifn; } ref4 = _this.properties; for (i = j = 0, len1 = ref4.length; j < len1; i = ++j) { prop = ref4[i]; if (!prop.soak) { continue; } prop.soak = false; fst = new Value(_this.base, _this.properties.slice(0, i)); snd = new Value(_this.base, _this.properties.slice(i)); if (fst.isComplex()) { ref = new Literal(o.scope.freeVariable('ref')); fst = new Parens(new Assign(ref, fst)); snd.base = ref; } return new If(new Existence(fst), snd, { soak: true }); } return false; }; })(this)(); }; return Value; })(Base); exports.Comment = Comment = (function(superClass1) { extend1(Comment, superClass1); function Comment(comment1) { this.comment = comment1; } Comment.prototype.isStatement = YES; Comment.prototype.makeReturn = THIS; Comment.prototype.compileNode = function(o, level) { var code, comment; comment = this.comment.replace(/^(\s*)#(?=\s)/gm, "$1 *"); code = "/*" + (multident(comment, this.tab)) + (indexOf.call(comment, '\n') >= 0 ? "\n" + this.tab : '') + " */"; if ((level || o.level) === LEVEL_TOP) { code = o.indent + code; } return [this.makeCode("\n"), this.makeCode(code)]; }; return Comment; })(Base); exports.Call = Call = (function(superClass1) { extend1(Call, superClass1); function Call(variable, args1, soak) { this.args = args1 != null ? args1 : []; this.soak = soak; this.isNew = false; this.isSuper = variable === 'super'; this.variable = this.isSuper ? null : variable; if (variable instanceof Value && variable.isNotCallable()) { variable.error("literal is not a function"); } } Call.prototype.children = ['variable', 'args']; Call.prototype.newInstance = function() { var base, ref3; base = ((ref3 = this.variable) != null ? ref3.base : void 0) || this.variable; if (base instanceof Call && !base.isNew) { base.newInstance(); } else { this.isNew = true; } return this; }; Call.prototype.superReference = function(o) { var accesses, base, bref, klass, method, name, nref, variable; method = o.scope.namedMethod(); if (method != null ? method.klass : void 0) { klass = method.klass, name = method.name, variable = method.variable; if (klass.isComplex()) { bref = new Literal(o.scope.parent.freeVariable('base')); base = new Value(new Parens(new Assign(bref, klass))); variable.base = base; variable.properties.splice(0, klass.properties.length); } if (name.isComplex() || (name instanceof Index && name.index.isAssignable())) { nref = new Literal(o.scope.parent.freeVariable('name')); name = new Index(new Assign(nref, name.index)); variable.properties.pop(); variable.properties.push(name); } accesses = [new Access(new Literal('__super__'))]; if (method["static"]) { accesses.push(new Access(new Literal('constructor'))); } accesses.push(nref != null ? new Index(nref) : name); return (new Value(bref != null ? bref : klass, accesses)).compile(o); } else if (method != null ? method.ctor : void 0) { return method.name + ".__super__.constructor"; } else { return this.error('cannot call super outside of an instance method.'); } }; Call.prototype.superThis = function(o) { var method; method = o.scope.method; return (method && !method.klass && method.context) || "this"; }; Call.prototype.unfoldSoak = function(o) { var call, ifn, j, left, len1, list, ref3, ref4, rite; if (this.soak) { if (this.variable) { if (ifn = unfoldSoak(o, this, 'variable')) { return ifn; } ref3 = new Value(this.variable).cacheReference(o), left = ref3[0], rite = ref3[1]; } else { left = new Literal(this.superReference(o)); rite = new Value(left); } rite = new Call(rite, this.args); rite.isNew = this.isNew; left = new Literal("typeof " + (left.compile(o)) + " === \"function\""); return new If(left, new Value(rite), { soak: true }); } call = this; list = []; while (true) { if (call.variable instanceof Call) { list.push(call); call = call.variable; continue; } if (!(call.variable instanceof Value)) { break; } list.push(call); if (!((call = call.variable.base) instanceof Call)) { break; } } ref4 = list.reverse(); for (j = 0, len1 = ref4.length; j < len1; j++) { call = ref4[j]; if (ifn) { if (call.variable instanceof Call) { call.variable = ifn; } else { call.variable.base = ifn; } } ifn = unfoldSoak(o, call, 'variable'); } return ifn; }; Call.prototype.compileNode = function(o) { var arg, argIndex, compiledArgs, compiledArray, fragments, j, len1, preface, ref3, ref4; if ((ref3 = this.variable) != null) { ref3.front = this.front; } compiledArray = Splat.compileSplattedArray(o, this.args, true); if (compiledArray.length) { return this.compileSplat(o, compiledArray); } compiledArgs = []; ref4 = this.args; for (argIndex = j = 0, len1 = ref4.length; j < len1; argIndex = ++j) { arg = ref4[argIndex]; if (argIndex) { compiledArgs.push(this.makeCode(", ")); } compiledArgs.push.apply(compiledArgs, arg.compileToFragments(o, LEVEL_LIST)); } fragments = []; if (this.isSuper) { preface = this.superReference(o) + (".call(" + (this.superThis(o))); if (compiledArgs.length) { preface += ", "; } fragments.push(this.makeCode(preface)); } else { if (this.isNew) { fragments.push(this.makeCode('new ')); } fragments.push.apply(fragments, this.variable.compileToFragments(o, LEVEL_ACCESS)); fragments.push(this.makeCode("(")); } fragments.push.apply(fragments, compiledArgs); fragments.push(this.makeCode(")")); return fragments; }; Call.prototype.compileSplat = function(o, splatArgs) { var answer, base, fun, idt, name, ref; if (this.isSuper) { return [].concat(this.makeCode((this.superReference(o)) + ".apply(" + (this.superThis(o)) + ", "), splatArgs, this.makeCode(")")); } if (this.isNew) { idt = this.tab + TAB; return [].concat(this.makeCode("(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args);\n" + idt + "return Object(result) === result ? result : child;\n" + this.tab + "})("), this.variable.compileToFragments(o, LEVEL_LIST), this.makeCode(", "), splatArgs, this.makeCode(", function(){})")); } answer = []; base = new Value(this.variable); if ((name = base.properties.pop()) && base.isComplex()) { ref = o.scope.freeVariable('ref'); answer = answer.concat(this.makeCode("(" + ref + " = "), base.compileToFragments(o, LEVEL_LIST), this.makeCode(")"), name.compileToFragments(o)); } else { fun = base.compileToFragments(o, LEVEL_ACCESS); if (SIMPLENUM.test(fragmentsToText(fun))) { fun = this.wrapInBraces(fun); } if (name) { ref = fragmentsToText(fun); fun.push.apply(fun, name.compileToFragments(o)); } else { ref = 'null'; } answer = answer.concat(fun); } return answer = answer.concat(this.makeCode(".apply(" + ref + ", "), splatArgs, this.makeCode(")")); }; return Call; })(Base); exports.Extends = Extends = (function(superClass1) { extend1(Extends, superClass1); function Extends(child1, parent1) { this.child = child1; this.parent = parent1; } Extends.prototype.children = ['child', 'parent']; Extends.prototype.compileToFragments = function(o) { return new Call(new Value(new Literal(utility('extend', o))), [this.child, this.parent]).compileToFragments(o); }; return Extends; })(Base); exports.Access = Access = (function(superClass1) { extend1(Access, superClass1); function Access(name1, tag) { this.name = name1; this.name.asKey = true; this.soak = tag === 'soak'; } Access.prototype.children = ['name']; Access.prototype.compileToFragments = function(o) { var name; name = this.name.compileToFragments(o); if (IDENTIFIER.test(fragmentsToText(name))) { name.unshift(this.makeCode(".")); } else { name.unshift(this.makeCode("[")); name.push(this.makeCode("]")); } return name; }; Access.prototype.isComplex = NO; return Access; })(Base); exports.Index = Index = (function(superClass1) { extend1(Index, superClass1); function Index(index1) { this.index = index1; } Index.prototype.children = ['index']; Index.prototype.compileToFragments = function(o) { return [].concat(this.makeCode("["), this.index.compileToFragments(o, LEVEL_PAREN), this.makeCode("]")); }; Index.prototype.isComplex = function() { return this.index.isComplex(); }; return Index; })(Base); exports.Range = Range = (function(superClass1) { extend1(Range, superClass1); Range.prototype.children = ['from', 'to']; function Range(from1, to1, tag) { this.from = from1; this.to = to1; this.exclusive = tag === 'exclusive'; this.equals = this.exclusive ? '' : '='; } Range.prototype.compileVariables = function(o) { var isComplex, ref3, ref4, ref5, ref6, step; o = merge(o, { top: true }); isComplex = del(o, 'isComplex'); ref3 = this.cacheToCodeFragments(this.from.cache(o, LEVEL_LIST, isComplex)), this.fromC = ref3[0], this.fromVar = ref3[1]; ref4 = this.cacheToCodeFragments(this.to.cache(o, LEVEL_LIST, isComplex)), this.toC = ref4[0], this.toVar = ref4[1]; if (step = del(o, 'step')) { ref5 = this.cacheToCodeFragments(step.cache(o, LEVEL_LIST, isComplex)), this.step = ref5[0], this.stepVar = ref5[1]; } ref6 = [this.fromVar.match(NUMBER), this.toVar.match(NUMBER)], this.fromNum = ref6[0], this.toNum = ref6[1]; if (this.stepVar) { return this.stepNum = this.stepVar.match(NUMBER); } }; Range.prototype.compileNode = function(o) { var cond, condPart, from, gt, idx, idxName, known, lt, namedIndex, ref3, ref4, stepPart, to, varPart; if (!this.fromVar) { this.compileVariables(o); } if (!o.index) { return this.compileArray(o); } known = this.fromNum && this.toNum; idx = del(o, 'index'); idxName = del(o, 'name'); namedIndex = idxName && idxName !== idx; varPart = idx + " = " + this.fromC; if (this.toC !== this.toVar) { varPart += ", " + this.toC; } if (this.step !== this.stepVar) { varPart += ", " + this.step; } ref3 = [idx + " <" + this.equals, idx + " >" + this.equals], lt = ref3[0], gt = ref3[1]; condPart = this.stepNum ? parseNum(this.stepNum[0]) > 0 ? lt + " " + this.toVar : gt + " " + this.toVar : known ? ((ref4 = [parseNum(this.fromNum[0]), parseNum(this.toNum[0])], from = ref4[0], to = ref4[1], ref4), from <= to ? lt + " " + to : gt + " " + to) : (cond = this.stepVar ? this.stepVar + " > 0" : this.fromVar + " <= " + this.toVar, cond + " ? " + lt + " " + this.toVar + " : " + gt + " " + this.toVar); stepPart = this.stepVar ? idx + " += " + this.stepVar : known ? namedIndex ? from <= to ? "++" + idx : "--" + idx : from <= to ? idx + "++" : idx + "--" : namedIndex ? cond + " ? ++" + idx + " : --" + idx : cond + " ? " + idx + "++ : " + idx + "--"; if (namedIndex) { varPart = idxName + " = " + varPart; } if (namedIndex) { stepPart = idxName + " = " + stepPart; } return [this.makeCode(varPart + "; " + condPart + "; " + stepPart)]; }; Range.prototype.compileArray = function(o) { var args, body, cond, hasArgs, i, idt, j, post, pre, range, ref3, ref4, result, results, vars; if (this.fromNum && this.toNum && Math.abs(this.fromNum - this.toNum) <= 20) { range = (function() { results = []; for (var j = ref3 = +this.fromNum, ref4 = +this.toNum; ref3 <= ref4 ? j <= ref4 : j >= ref4; ref3 <= ref4 ? j++ : j--){ results.push(j); } return results; }).apply(this); if (this.exclusive) { range.pop(); } return [this.makeCode("[" + (range.join(', ')) + "]")]; } idt = this.tab + TAB; i = o.scope.freeVariable('i', { single: true }); result = o.scope.freeVariable('results'); pre = "\n" + idt + result + " = [];"; if (this.fromNum && this.toNum) { o.index = i; body = fragmentsToText(this.compileNode(o)); } else { vars = (i + " = " + this.fromC) + (this.toC !== this.toVar ? ", " + this.toC : ''); cond = this.fromVar + " <= " + this.toVar; body = "var " + vars + "; " + cond + " ? " + i + " <" + this.equals + " " + this.toVar + " : " + i + " >" + this.equals + " " + this.toVar + "; " + cond + " ? " + i + "++ : " + i + "--"; } post = "{ " + result + ".push(" + i + "); }\n" + idt + "return " + result + ";\n" + o.indent; hasArgs = function(node) { return node != null ? node.contains(isLiteralArguments) : void 0; }; if (hasArgs(this.from) || hasArgs(this.to)) { args = ', arguments'; } return [this.makeCode("(function() {" + pre + "\n" + idt + "for (" + body + ")" + post + "}).apply(this" + (args != null ? args : '') + ")")]; }; return Range; })(Base); exports.Slice = Slice = (function(superClass1) { extend1(Slice, superClass1); Slice.prototype.children = ['range']; function Slice(range1) { this.range = range1; Slice.__super__.constructor.call(this); } Slice.prototype.compileNode = function(o) { var compiled, compiledText, from, fromCompiled, ref3, to, toStr; ref3 = this.range, to = ref3.to, from = ref3.from; fromCompiled = from && from.compileToFragments(o, LEVEL_PAREN) || [this.makeCode('0')]; if (to) { compiled = to.compileToFragments(o, LEVEL_PAREN); compiledText = fragmentsToText(compiled); if (!(!this.range.exclusive && +compiledText === -1)) { toStr = ', ' + (this.range.exclusive ? compiledText : SIMPLENUM.test(compiledText) ? "" + (+compiledText + 1) : (compiled = to.compileToFragments(o, LEVEL_ACCESS), "+" + (fragmentsToText(compiled)) + " + 1 || 9e9")); } } return [this.makeCode(".slice(" + (fragmentsToText(fromCompiled)) + (toStr || '') + ")")]; }; return Slice; })(Base); exports.Obj = Obj = (function(superClass1) { extend1(Obj, superClass1); function Obj(props, generated) { this.generated = generated != null ? generated : false; this.objects = this.properties = props || []; } Obj.prototype.children = ['properties']; Obj.prototype.compileNode = function(o) { var answer, dynamicIndex, hasDynamic, i, idt, indent, j, join, k, key, l, lastNoncom, len1, len2, len3, node, oref, prop, props, ref3, value; props = this.properties; if (this.generated) { for (j = 0, len1 = props.length; j < len1; j++) { node = props[j]; if (node instanceof Value) { node.error('cannot have an implicit value in an implicit object'); } } } for (dynamicIndex = k = 0, len2 = props.length; k < len2; dynamicIndex = ++k) { prop = props[dynamicIndex]; if ((prop.variable || prop).base instanceof Parens) { break; } } hasDynamic = dynamicIndex < props.length; idt = o.indent += TAB; lastNoncom = this.lastNonComment(this.properties); answer = []; if (hasDynamic) { oref = o.scope.freeVariable('obj'); answer.push(this.makeCode("(\n" + idt + oref + " = ")); } answer.push(this.makeCode("{" + (props.length === 0 || dynamicIndex === 0 ? '}' : '\n'))); for (i = l = 0, len3 = props.length; l < len3; i = ++l) { prop = props[i]; if (i === dynamicIndex) { if (i !== 0) { answer.push(this.makeCode("\n" + idt + "}")); } answer.push(this.makeCode(',\n')); } join = i === props.length - 1 || i === dynamicIndex - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\n' : ',\n'; indent = prop instanceof Comment ? '' : idt; if (hasDynamic && i < dynamicIndex) { indent += TAB; } if (prop instanceof Assign && prop.variable instanceof Value && prop.variable.hasProperties()) { prop.variable.error('invalid object key'); } if (prop instanceof Value && prop["this"]) { prop = new Assign(prop.properties[0].name, prop, 'object'); } if (!(prop instanceof Comment)) { if (i < dynamicIndex) { if (!(prop instanceof Assign)) { prop = new Assign(prop, prop, 'object'); } (prop.variable.base || prop.variable).asKey = true; } else { if (prop instanceof Assign) { key = prop.variable; value = prop.value; } else { ref3 = prop.base.cache(o), key = ref3[0], value = ref3[1]; } prop = new Assign(new Value(new Literal(oref), [new Access(key)]), value); } } if (indent) { answer.push(this.makeCode(indent)); } answer.push.apply(answer, prop.compileToFragments(o, LEVEL_TOP)); if (join) { answer.push(this.makeCode(join)); } } if (hasDynamic) { answer.push(this.makeCode(",\n" + idt + oref + "\n" + this.tab + ")")); } else { if (props.length !== 0) { answer.push(this.makeCode("\n" + this.tab + "}")); } } if (this.front && !hasDynamic) { return this.wrapInBraces(answer); } else { return answer; } }; Obj.prototype.assigns = function(name) { var j, len1, prop, ref3; ref3 = this.properties; for (j = 0, len1 = ref3.length; j < len1; j++) { prop = ref3[j]; if (prop.assigns(name)) { return true; } } return false; }; return Obj; })(Base); exports.Arr = Arr = (function(superClass1) { extend1(Arr, superClass1); function Arr(objs) { this.objects = objs || []; } Arr.prototype.children = ['objects']; Arr.prototype.compileNode = function(o) { var answer, compiledObjs, fragments, index, j, len1, obj; if (!this.objects.length) { return [this.makeCode('[]')]; } o.indent += TAB; answer = Splat.compileSplattedArray(o, this.objects); if (answer.length) { return answer; } answer = []; compiledObjs = (function() { var j, len1, ref3, results; ref3 = this.objects; results = []; for (j = 0, len1 = ref3.length; j < len1; j++) { obj = ref3[j]; results.push(obj.compileToFragments(o, LEVEL_LIST)); } return results; }).call(this); for (index = j = 0, len1 = compiledObjs.length; j < len1; index = ++j) { fragments = compiledObjs[index]; if (index) { answer.push(this.makeCode(", ")); } answer.push.apply(answer, fragments); } if (fragmentsToText(answer).indexOf('\n') >= 0) { answer.unshift(this.makeCode("[\n" + o.indent)); answer.push(this.makeCode("\n" + this.tab + "]")); } else { answer.unshift(this.makeCode("[")); answer.push(this.makeCode("]")); } return answer; }; Arr.prototype.assigns = function(name) { var j, len1, obj, ref3; ref3 = this.objects; for (j = 0, len1 = ref3.length; j < len1; j++) { obj = ref3[j]; if (obj.assigns(name)) { return true; } } return false; }; return Arr; })(Base); exports.Class = Class = (function(superClass1) { extend1(Class, superClass1); function Class(variable1, parent1, body1) { this.variable = variable1; this.parent = parent1; this.body = body1 != null ? body1 : new Block; this.boundFuncs = []; this.body.classBody = true; } Class.prototype.children = ['variable', 'parent', 'body']; Class.prototype.determineName = function() { var decl, ref3, tail; if (!this.variable) { return null; } ref3 = this.variable.properties, tail = ref3[ref3.length - 1]; decl = tail ? tail instanceof Access && tail.name.value : this.variable.base.value; if (indexOf.call(STRICT_PROSCRIBED, decl) >= 0) { this.variable.error("class variable name may not be " + decl); } return decl && (decl = IDENTIFIER.test(decl) && decl); }; Class.prototype.setContext = function(name) { return this.body.traverseChildren(false, function(node) { if (node.classBody) { return false; } if (node instanceof Literal && node.value === 'this') { return node.value = name; } else if (node instanceof Code) { if (node.bound) { return node.context = name; } } }); }; Class.prototype.addBoundFunctions = function(o) { var bvar, j, len1, lhs, ref3; ref3 = this.boundFuncs; for (j = 0, len1 = ref3.length; j < len1; j++) { bvar = ref3[j]; lhs = (new Value(new Literal("this"), [new Access(bvar)])).compile(o); this.ctor.body.unshift(new Literal(lhs + " = " + (utility('bind', o)) + "(" + lhs + ", this)")); } }; Class.prototype.addProperties = function(node, name, o) { var acc, assign, base, exprs, func, props; props = node.base.properties.slice(0); exprs = (function() { var results; results = []; while (assign = props.shift()) { if (assign instanceof Assign) { base = assign.variable.base; delete assign.context; func = assign.value; if (base.value === 'constructor') { if (this.ctor) { assign.error('cannot define more than one constructor in a class'); } if (func.bound) { assign.error('cannot define a constructor as a bound function'); } if (func instanceof Code) { assign = this.ctor = func; } else { this.externalCtor = o.classScope.freeVariable('class'); assign = new Assign(new Literal(this.externalCtor), func); } } else { if (assign.variable["this"]) { func["static"] = true; } else { acc = base.isComplex() ? new Index(base) : new Access(base); assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), acc]); if (func instanceof Code && func.bound) { this.boundFuncs.push(base); func.bound = false; } } } } results.push(assign); } return results; }).call(this); return compact(exprs); }; Class.prototype.walkBody = function(name, o) { return this.traverseChildren(false, (function(_this) { return function(child) { var cont, exps, i, j, len1, node, ref3; cont = true; if (child instanceof Class) { return false; } if (child instanceof Block) { ref3 = exps = child.expressions; for (i = j = 0, len1 = ref3.length; j < len1; i = ++j) { node = ref3[i]; if (node instanceof Assign && node.variable.looksStatic(name)) { node.value["static"] = true; } else if (node instanceof Value && node.isObject(true)) { cont = false; exps[i] = _this.addProperties(node, name, o); } } child.expressions = exps = flatten(exps); } return cont && !(child instanceof Class); }; })(this)); }; Class.prototype.hoistDirectivePrologue = function() { var expressions, index, node; index = 0; expressions = this.body.expressions; while ((node = expressions[index]) && node instanceof Comment || node instanceof Value && node.isString()) { ++index; } return this.directives = expressions.splice(0, index); }; Class.prototype.ensureConstructor = function(name) { if (!this.ctor) { this.ctor = new Code; if (this.externalCtor) { this.ctor.body.push(new Literal(this.externalCtor + ".apply(this, arguments)")); } else if (this.parent) { this.ctor.body.push(new Literal(name + ".__super__.constructor.apply(this, arguments)")); } this.ctor.body.makeReturn(); this.body.expressions.unshift(this.ctor); } this.ctor.ctor = this.ctor.name = name; this.ctor.klass = null; return this.ctor.noReturn = true; }; Class.prototype.compileNode = function(o) { var args, argumentsNode, func, jumpNode, klass, lname, name, ref3, superClass; if (jumpNode = this.body.jumps()) { jumpNode.error('Class bodies cannot contain pure statements'); } if (argumentsNode = this.body.contains(isLiteralArguments)) { argumentsNode.error("Class bodies shouldn't reference arguments"); } name = this.determineName() || '_Class'; if (name.reserved) { name = "_" + name; } lname = new Literal(name); func = new Code([], Block.wrap([this.body])); args = []; o.classScope = func.makeScope(o.scope); this.hoistDirectivePrologue(); this.setContext(name); this.walkBody(name, o); this.ensureConstructor(name); this.addBoundFunctions(o); this.body.spaced = true; this.body.expressions.push(lname); if (this.parent) { superClass = new Literal(o.classScope.freeVariable('superClass', { reserve: false })); this.body.expressions.unshift(new Extends(lname, superClass)); func.params.push(new Param(superClass)); args.push(this.parent); } (ref3 = this.body.expressions).unshift.apply(ref3, this.directives); klass = new Parens(new Call(func, args)); if (this.variable) { klass = new Assign(this.variable, klass); } return klass.compileToFragments(o); }; return Class; })(Base); exports.Assign = Assign = (function(superClass1) { extend1(Assign, superClass1); function Assign(variable1, value1, context, options) { var forbidden, name, ref3; this.variable = variable1; this.value = value1; this.context = context; this.param = options && options.param; this.subpattern = options && options.subpattern; forbidden = (ref3 = (name = this.variable.unwrapAll().value), indexOf.call(STRICT_PROSCRIBED, ref3) >= 0); if (forbidden && this.context !== 'object') { this.variable.error("variable name may not be \"" + name + "\""); } } Assign.prototype.children = ['variable', 'value']; Assign.prototype.isStatement = function(o) { return (o != null ? o.level : void 0) === LEVEL_TOP && (this.context != null) && indexOf.call(this.context, "?") >= 0; }; Assign.prototype.assigns = function(name) { return this[this.context === 'object' ? 'value' : 'variable'].assigns(name); }; Assign.prototype.unfoldSoak = function(o) { return unfoldSoak(o, this, 'variable'); }; Assign.prototype.compileNode = function(o) { var answer, compiledName, isValue, j, name, properties, prototype, ref3, ref4, ref5, ref6, ref7, val, varBase; if (isValue = this.variable instanceof Value) { if (this.variable.isArray() || this.variable.isObject()) { return this.compilePatternMatch(o); } if (this.variable.isSplice()) { return this.compileSplice(o); } if ((ref3 = this.context) === '||=' || ref3 === '&&=' || ref3 === '?=') { return this.compileConditional(o); } if ((ref4 = this.context) === '**=' || ref4 === '//=' || ref4 === '%%=') { return this.compileSpecialMath(o); } } if (this.value instanceof Code) { if (this.value["static"]) { this.value.klass = this.variable.base; this.value.name = this.variable.properties[0]; this.value.variable = this.variable; } else if (((ref5 = this.variable.properties) != null ? ref5.length : void 0) >= 2) { ref6 = this.variable.properties, properties = 3 <= ref6.length ? slice.call(ref6, 0, j = ref6.length - 2) : (j = 0, []), prototype = ref6[j++], name = ref6[j++]; if (((ref7 = prototype.name) != null ? ref7.value : void 0) === 'prototype') { this.value.klass = new Value(this.variable.base, properties); this.value.name = name; this.value.variable = this.variable; } } } if (!this.context) { varBase = this.variable.unwrapAll(); if (!varBase.isAssignable()) { this.variable.error("\"" + (this.variable.compile(o)) + "\" cannot be assigned"); } if (!(typeof varBase.hasProperties === "function" ? varBase.hasProperties() : void 0)) { if (this.param) { o.scope.add(varBase.value, 'var'); } else { o.scope.find(varBase.value); } } } val = this.value.compileToFragments(o, LEVEL_LIST); compiledName = this.variable.compileToFragments(o, LEVEL_LIST); if (this.context === 'object') { return compiledName.concat(this.makeCode(": "), val); } answer = compiledName.concat(this.makeCode(" " + (this.context || '=') + " "), val); if (o.level <= LEVEL_LIST) { return answer; } else { return this.wrapInBraces(answer); } }; Assign.prototype.compilePatternMatch = function(o) { var acc, assigns, code, expandedIdx, fragments, i, idx, isObject, ivar, j, len1, name, obj, objects, olen, ref, ref3, ref4, ref5, ref6, ref7, ref8, rest, top, val, value, vvar, vvarText; top = o.level === LEVEL_TOP; value = this.value; objects = this.variable.base.objects; if (!(olen = objects.length)) { code = value.compileToFragments(o); if (o.level >= LEVEL_OP) { return this.wrapInBraces(code); } else { return code; } } isObject = this.variable.isObject(); if (top && olen === 1 && !((obj = objects[0]) instanceof Splat)) { if (obj instanceof Assign) { ref3 = obj, (ref4 = ref3.variable, idx = ref4.base), obj = ref3.value; } else { idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new Literal(0); } acc = IDENTIFIER.test(idx.unwrap().value || 0); value = new Value(value); value.properties.push(new (acc ? Access : Index)(idx)); if (ref5 = obj.unwrap().value, indexOf.call(RESERVED, ref5) >= 0) { obj.error("assignment to a reserved word: " + (obj.compile(o))); } return new Assign(obj, value, null, { param: this.param }).compileToFragments(o, LEVEL_TOP); } vvar = value.compileToFragments(o, LEVEL_LIST); vvarText = fragmentsToText(vvar); assigns = []; expandedIdx = false; if (!IDENTIFIER.test(vvarText) || this.variable.assigns(vvarText)) { assigns.push([this.makeCode((ref = o.scope.freeVariable('ref')) + " = ")].concat(slice.call(vvar))); vvar = [this.makeCode(ref)]; vvarText = ref; } for (i = j = 0, len1 = objects.length; j < len1; i = ++j) { obj = objects[i]; idx = i; if (isObject) { if (obj instanceof Assign) { ref6 = obj, (ref7 = ref6.variable, idx = ref7.base), obj = ref6.value; } else { if (obj.base instanceof Parens) { ref8 = new Value(obj.unwrapAll()).cacheReference(o), obj = ref8[0], idx = ref8[1]; } else { idx = obj["this"] ? obj.properties[0].name : obj; } } } if (!expandedIdx && obj instanceof Splat) { name = obj.name.unwrap().value; obj = obj.unwrap(); val = olen + " <= " + vvarText + ".length ? " + (utility('slice', o)) + ".call(" + vvarText + ", " + i; if (rest = olen - i - 1) { ivar = o.scope.freeVariable('i', { single: true }); val += ", " + ivar + " = " + vvarText + ".length - " + rest + ") : (" + ivar + " = " + i + ", [])"; } else { val += ") : []"; } val = new Literal(val); expandedIdx = ivar + "++"; } else if (!expandedIdx && obj instanceof Expansion) { if (rest = olen - i - 1) { if (rest === 1) { expandedIdx = vvarText + ".length - 1"; } else { ivar = o.scope.freeVariable('i', { single: true }); val = new Literal(ivar + " = " + vvarText + ".length - " + rest); expandedIdx = ivar + "++"; assigns.push(val.compileToFragments(o, LEVEL_LIST)); } } continue; } else { name = obj.unwrap().value; if (obj instanceof Splat || obj instanceof Expansion) { obj.error("multiple splats/expansions are disallowed in an assignment"); } if (typeof idx === 'number') { idx = new Literal(expandedIdx || idx); acc = false; } else { acc = isObject && IDENTIFIER.test(idx.unwrap().value || 0); } val = new Value(new Literal(vvarText), [new (acc ? Access : Index)(idx)]); } if ((name != null) && indexOf.call(RESERVED, name) >= 0) { obj.error("assignment to a reserved word: " + (obj.compile(o))); } assigns.push(new Assign(obj, val, null, { param: this.param, subpattern: true }).compileToFragments(o, LEVEL_LIST)); } if (!(top || this.subpattern)) { assigns.push(vvar); } fragments = this.joinFragmentArrays(assigns, ', '); if (o.level < LEVEL_LIST) { return fragments; } else { return this.wrapInBraces(fragments); } }; Assign.prototype.compileConditional = function(o) { var fragments, left, ref3, right; ref3 = this.variable.cacheReference(o), left = ref3[0], right = ref3[1]; if (!left.properties.length && left.base instanceof Literal && left.base.value !== "this" && !o.scope.check(left.base.value)) { this.variable.error("the variable \"" + left.base.value + "\" can't be assigned with " + this.context + " because it has not been declared before"); } if (indexOf.call(this.context, "?") >= 0) { o.isExistentialEquals = true; return new If(new Existence(left), right, { type: 'if' }).addElse(new Assign(right, this.value, '=')).compileToFragments(o); } else { fragments = new Op(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compileToFragments(o); if (o.level <= LEVEL_LIST) { return fragments; } else { return this.wrapInBraces(fragments); } } }; Assign.prototype.compileSpecialMath = function(o) { var left, ref3, right; ref3 = this.variable.cacheReference(o), left = ref3[0], right = ref3[1]; return new Assign(left, new Op(this.context.slice(0, -1), right, this.value)).compileToFragments(o); }; Assign.prototype.compileSplice = function(o) { var answer, exclusive, from, fromDecl, fromRef, name, ref3, ref4, ref5, to, valDef, valRef; ref3 = this.variable.properties.pop().range, from = ref3.from, to = ref3.to, exclusive = ref3.exclusive; name = this.variable.compile(o); if (from) { ref4 = this.cacheToCodeFragments(from.cache(o, LEVEL_OP)), fromDecl = ref4[0], fromRef = ref4[1]; } else { fromDecl = fromRef = '0'; } if (to) { if (from instanceof Value && from.isSimpleNumber() && to instanceof Value && to.isSimpleNumber()) { to = to.compile(o) - fromRef; if (!exclusive) { to += 1; } } else { to = to.compile(o, LEVEL_ACCESS) + ' - ' + fromRef; if (!exclusive) { to += ' + 1'; } } } else { to = "9e9"; } ref5 = this.value.cache(o, LEVEL_LIST), valDef = ref5[0], valRef = ref5[1]; answer = [].concat(this.makeCode("[].splice.apply(" + name + ", [" + fromDecl + ", " + to + "].concat("), valDef, this.makeCode(")), "), valRef); if (o.level > LEVEL_TOP) { return this.wrapInBraces(answer); } else { return answer; } }; return Assign; })(Base); exports.Code = Code = (function(superClass1) { extend1(Code, superClass1); function Code(params, body, tag) { this.params = params || []; this.body = body || new Block; this.bound = tag === 'boundfunc'; this.isGenerator = !!this.body.contains(function(node) { var ref3; return node instanceof Op && ((ref3 = node.operator) === 'yield' || ref3 === 'yield*'); }); } Code.prototype.children = ['params', 'body']; Code.prototype.isStatement = function() { return !!this.ctor; }; Code.prototype.jumps = NO; Code.prototype.makeScope = function(parentScope) { return new Scope(parentScope, this.body, this); }; Code.prototype.compileNode = function(o) { var answer, boundfunc, code, exprs, i, j, k, l, len1, len2, len3, len4, len5, len6, lit, m, p, param, params, q, r, ref, ref3, ref4, ref5, ref6, ref7, ref8, splats, uniqs, val, wasEmpty, wrapper; if (this.bound && ((ref3 = o.scope.method) != null ? ref3.bound : void 0)) { this.context = o.scope.method.context; } if (this.bound && !this.context) { this.context = '_this'; wrapper = new Code([new Param(new Literal(this.context))], new Block([this])); boundfunc = new Call(wrapper, [new Literal('this')]); boundfunc.updateLocationDataIfMissing(this.locationData); return boundfunc.compileNode(o); } o.scope = del(o, 'classScope') || this.makeScope(o.scope); o.scope.shared = del(o, 'sharedScope'); o.indent += TAB; delete o.bare; delete o.isExistentialEquals; params = []; exprs = []; ref4 = this.params; for (j = 0, len1 = ref4.length; j < len1; j++) { param = ref4[j]; if (!(param instanceof Expansion)) { o.scope.parameter(param.asReference(o)); } } ref5 = this.params; for (k = 0, len2 = ref5.length; k < len2; k++) { param = ref5[k]; if (!(param.splat || param instanceof Expansion)) { continue; } ref6 = this.params; for (l = 0, len3 = ref6.length; l < len3; l++) { p = ref6[l]; if (!(p instanceof Expansion) && p.name.value) { o.scope.add(p.name.value, 'var', true); } } splats = new Assign(new Value(new Arr((function() { var len4, m, ref7, results; ref7 = this.params; results = []; for (m = 0, len4 = ref7.length; m < len4; m++) { p = ref7[m]; results.push(p.asReference(o)); } return results; }).call(this))), new Value(new Literal('arguments'))); break; } ref7 = this.params; for (m = 0, len4 = ref7.length; m < len4; m++) { param = ref7[m]; if (param.isComplex()) { val = ref = param.asReference(o); if (param.value) { val = new Op('?', ref, param.value); } exprs.push(new Assign(new Value(param.name), val, '=', { param: true })); } else { ref = param; if (param.value) { lit = new Literal(ref.name.value + ' == null'); val = new Assign(new Value(param.name), param.value, '='); exprs.push(new If(lit, val)); } } if (!splats) { params.push(ref); } } wasEmpty = this.body.isEmpty(); if (splats) { exprs.unshift(splats); } if (exprs.length) { (ref8 = this.body.expressions).unshift.apply(ref8, exprs); } for (i = q = 0, len5 = params.length; q < len5; i = ++q) { p = params[i]; params[i] = p.compileToFragments(o); o.scope.parameter(fragmentsToText(params[i])); } uniqs = []; this.eachParamName(function(name, node) { if (indexOf.call(uniqs, name) >= 0) { node.error("multiple parameters named " + name); } return uniqs.push(name); }); if (!(wasEmpty || this.noReturn)) { this.body.makeReturn(); } code = 'function'; if (this.isGenerator) { code += '*'; } if (this.ctor) { code += ' ' + this.name; } code += '('; answer = [this.makeCode(code)]; for (i = r = 0, len6 = params.length; r < len6; i = ++r) { p = params[i]; if (i) { answer.push(this.makeCode(", ")); } answer.push.apply(answer, p); } answer.push(this.makeCode(') {')); if (!this.body.isEmpty()) { answer = answer.concat(this.makeCode("\n"), this.body.compileWithDeclarations(o), this.makeCode("\n" + this.tab)); } answer.push(this.makeCode('}')); if (this.ctor) { return [this.makeCode(this.tab)].concat(slice.call(answer)); } if (this.front || (o.level >= LEVEL_ACCESS)) { return this.wrapInBraces(answer); } else { return answer; } }; Code.prototype.eachParamName = function(iterator) { var j, len1, param, ref3, results; ref3 = this.params; results = []; for (j = 0, len1 = ref3.length; j < len1; j++) { param = ref3[j]; results.push(param.eachName(iterator)); } return results; }; Code.prototype.traverseChildren = function(crossScope, func) { if (crossScope) { return Code.__super__.traverseChildren.call(this, crossScope, func); } }; return Code; })(Base); exports.Param = Param = (function(superClass1) { extend1(Param, superClass1); function Param(name1, value1, splat) { var name, ref3; this.name = name1; this.value = value1; this.splat = splat; if (ref3 = (name = this.name.unwrapAll().value), indexOf.call(STRICT_PROSCRIBED, ref3) >= 0) { this.name.error("parameter name \"" + name + "\" is not allowed"); } } Param.prototype.children = ['name', 'value']; Param.prototype.compileToFragments = function(o) { return this.name.compileToFragments(o, LEVEL_LIST); }; Param.prototype.asReference = function(o) { var name, node; if (this.reference) { return this.reference; } node = this.name; if (node["this"]) { name = node.properties[0].name.value; if (name.reserved) { name = "_" + name; } node = new Literal(o.scope.freeVariable(name)); } else if (node.isComplex()) { node = new Literal(o.scope.freeVariable('arg')); } node = new Value(node); if (this.splat) { node = new Splat(node); } node.updateLocationDataIfMissing(this.locationData); return this.reference = node; }; Param.prototype.isComplex = function() { return this.name.isComplex(); }; Param.prototype.eachName = function(iterator, name) { var atParam, j, len1, node, obj, ref3; if (name == null) { name = this.name; } atParam = function(obj) { return iterator("@" + obj.properties[0].name.value, obj); }; if (name instanceof Literal) { return iterator(name.value, name); } if (name instanceof Value) { return atParam(name); } ref3 = name.objects; for (j = 0, len1 = ref3.length; j < len1; j++) { obj = ref3[j]; if (obj instanceof Assign) { this.eachName(iterator, obj.value.unwrap()); } else if (obj instanceof Splat) { node = obj.name.unwrap(); iterator(node.value, node); } else if (obj instanceof Value) { if (obj.isArray() || obj.isObject()) { this.eachName(iterator, obj.base); } else if (obj["this"]) { atParam(obj); } else { iterator(obj.base.value, obj.base); } } else if (!(obj instanceof Expansion)) { obj.error("illegal parameter " + (obj.compile())); } } }; return Param; })(Base); exports.Splat = Splat = (function(superClass1) { extend1(Splat, superClass1); Splat.prototype.children = ['name']; Splat.prototype.isAssignable = YES; function Splat(name) { this.name = name.compile ? name : new Literal(name); } Splat.prototype.assigns = function(name) { return this.name.assigns(name); }; Splat.prototype.compileToFragments = function(o) { return this.name.compileToFragments(o); }; Splat.prototype.unwrap = function() { return this.name; }; Splat.compileSplattedArray = function(o, list, apply) { var args, base, compiledNode, concatPart, fragments, i, index, j, last, len1, node; index = -1; while ((node = list[++index]) && !(node instanceof Splat)) { continue; } if (index >= list.length) { return []; } if (list.length === 1) { node = list[0]; fragments = node.compileToFragments(o, LEVEL_LIST); if (apply) { return fragments; } return [].concat(node.makeCode((utility('slice', o)) + ".call("), fragments, node.makeCode(")")); } args = list.slice(index); for (i = j = 0, len1 = args.length; j < len1; i = ++j) { node = args[i]; compiledNode = node.compileToFragments(o, LEVEL_LIST); args[i] = node instanceof Splat ? [].concat(node.makeCode((utility('slice', o)) + ".call("), compiledNode, node.makeCode(")")) : [].concat(node.makeCode("["), compiledNode, node.makeCode("]")); } if (index === 0) { node = list[0]; concatPart = node.joinFragmentArrays(args.slice(1), ', '); return args[0].concat(node.makeCode(".concat("), concatPart, node.makeCode(")")); } base = (function() { var k, len2, ref3, results; ref3 = list.slice(0, index); results = []; for (k = 0, len2 = ref3.length; k < len2; k++) { node = ref3[k]; results.push(node.compileToFragments(o, LEVEL_LIST)); } return results; })(); base = list[0].joinFragmentArrays(base, ', '); concatPart = list[index].joinFragmentArrays(args, ', '); last = list[list.length - 1]; return [].concat(list[0].makeCode("["), base, list[index].makeCode("].concat("), concatPart, last.makeCode(")")); }; return Splat; })(Base); exports.Expansion = Expansion = (function(superClass1) { extend1(Expansion, superClass1); function Expansion() { return Expansion.__super__.constructor.apply(this, arguments); } Expansion.prototype.isComplex = NO; Expansion.prototype.compileNode = function(o) { return this.error('Expansion must be used inside a destructuring assignment or parameter list'); }; Expansion.prototype.asReference = function(o) { return this; }; Expansion.prototype.eachName = function(iterator) {}; return Expansion; })(Base); exports.While = While = (function(superClass1) { extend1(While, superClass1); function While(condition, options) { this.condition = (options != null ? options.invert : void 0) ? condition.invert() : condition; this.guard = options != null ? options.guard : void 0; } While.prototype.children = ['condition', 'guard', 'body']; While.prototype.isStatement = YES; While.prototype.makeReturn = function(res) { if (res) { return While.__super__.makeReturn.apply(this, arguments); } else { this.returns = !this.jumps({ loop: true }); return this; } }; While.prototype.addBody = function(body1) { this.body = body1; return this; }; While.prototype.jumps = function() { var expressions, j, jumpNode, len1, node; expressions = this.body.expressions; if (!expressions.length) { return false; } for (j = 0, len1 = expressions.length; j < len1; j++) { node = expressions[j]; if (jumpNode = node.jumps({ loop: true })) { return jumpNode; } } return false; }; While.prototype.compileNode = function(o) { var answer, body, rvar, set; o.indent += TAB; set = ''; body = this.body; if (body.isEmpty()) { body = this.makeCode(''); } else { if (this.returns) { body.makeReturn(rvar = o.scope.freeVariable('results')); set = "" + this.tab + rvar + " = [];\n"; } if (this.guard) { if (body.expressions.length > 1) { body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue"))); } else { if (this.guard) { body = Block.wrap([new If(this.guard, body)]); } } } body = [].concat(this.makeCode("\n"), body.compileToFragments(o, LEVEL_TOP), this.makeCode("\n" + this.tab)); } answer = [].concat(this.makeCode(set + this.tab + "while ("), this.condition.compileToFragments(o, LEVEL_PAREN), this.makeCode(") {"), body, this.makeCode("}")); if (this.returns) { answer.push(this.makeCode("\n" + this.tab + "return " + rvar + ";")); } return answer; }; return While; })(Base); exports.Op = Op = (function(superClass1) { var CONVERSIONS, INVERSIONS; extend1(Op, superClass1); function Op(op, first, second, flip) { if (op === 'in') { return new In(first, second); } if (op === 'do') { return this.generateDo(first); } if (op === 'new') { if (first instanceof Call && !first["do"] && !first.isNew) { return first.newInstance(); } if (first instanceof Code && first.bound || first["do"]) { first = new Parens(first); } } this.operator = CONVERSIONS[op] || op; this.first = first; this.second = second; this.flip = !!flip; return this; } CONVERSIONS = { '==': '===', '!=': '!==', 'of': 'in', 'yieldfrom': 'yield*' }; INVERSIONS = { '!==': '===', '===': '!==' }; Op.prototype.children = ['first', 'second']; Op.prototype.isSimpleNumber = NO; Op.prototype.isYield = function() { var ref3; return (ref3 = this.operator) === 'yield' || ref3 === 'yield*'; }; Op.prototype.isYieldReturn = function() { return this.isYield() && this.first instanceof Return; }; Op.prototype.isUnary = function() { return !this.second; }; Op.prototype.isComplex = function() { var ref3; return !(this.isUnary() && ((ref3 = this.operator) === '+' || ref3 === '-') && this.first instanceof Value && this.first.isSimpleNumber()); }; Op.prototype.isChainable = function() { var ref3; return (ref3 = this.operator) === '<' || ref3 === '>' || ref3 === '>=' || ref3 === '<=' || ref3 === '===' || ref3 === '!=='; }; Op.prototype.invert = function() { var allInvertable, curr, fst, op, ref3; if (this.isChainable() && this.first.isChainable()) { allInvertable = true; curr = this; while (curr && curr.operator) { allInvertable && (allInvertable = curr.operator in INVERSIONS); curr = curr.first; } if (!allInvertable) { return new Parens(this).invert(); } curr = this; while (curr && curr.operator) { curr.invert = !curr.invert; curr.operator = INVERSIONS[curr.operator]; curr = curr.first; } return this; } else if (op = INVERSIONS[this.operator]) { this.operator = op; if (this.first.unwrap() instanceof Op) { this.first.invert(); } return this; } else if (this.second) { return new Parens(this).invert(); } else if (this.operator === '!' && (fst = this.first.unwrap()) instanceof Op && ((ref3 = fst.operator) === '!' || ref3 === 'in' || ref3 === 'instanceof')) { return fst; } else { return new Op('!', this); } }; Op.prototype.unfoldSoak = function(o) { var ref3; return ((ref3 = this.operator) === '++' || ref3 === '--' || ref3 === 'delete') && unfoldSoak(o, this, 'first'); }; Op.prototype.generateDo = function(exp) { var call, func, j, len1, param, passedParams, ref, ref3; passedParams = []; func = exp instanceof Assign && (ref = exp.value.unwrap()) instanceof Code ? ref : exp; ref3 = func.params || []; for (j = 0, len1 = ref3.length; j < len1; j++) { param = ref3[j]; if (param.value) { passedParams.push(param.value); delete param.value; } else { passedParams.push(param); } } call = new Call(exp, passedParams); call["do"] = true; return call; }; Op.prototype.compileNode = function(o) { var answer, isChain, lhs, ref3, ref4, rhs; isChain = this.isChainable() && this.first.isChainable(); if (!isChain) { this.first.front = this.front; } if (this.operator === 'delete' && o.scope.check(this.first.unwrapAll().value)) { this.error('delete operand may not be argument or var'); } if (((ref3 = this.operator) === '--' || ref3 === '++') && (ref4 = this.first.unwrapAll().value, indexOf.call(STRICT_PROSCRIBED, ref4) >= 0)) { this.error("cannot increment/decrement \"" + (this.first.unwrapAll().value) + "\""); } if (this.isYield()) { return this.compileYield(o); } if (this.isUnary()) { return this.compileUnary(o); } if (isChain) { return this.compileChain(o); } switch (this.operator) { case '?': return this.compileExistence(o); case '**': return this.compilePower(o); case '//': return this.compileFloorDivision(o); case '%%': return this.compileModulo(o); default: lhs = this.first.compileToFragments(o, LEVEL_OP); rhs = this.second.compileToFragments(o, LEVEL_OP); answer = [].concat(lhs, this.makeCode(" " + this.operator + " "), rhs); if (o.level <= LEVEL_OP) { return answer; } else { return this.wrapInBraces(answer); } } }; Op.prototype.compileChain = function(o) { var fragments, fst, ref3, shared; ref3 = this.first.second.cache(o), this.first.second = ref3[0], shared = ref3[1]; fst = this.first.compileToFragments(o, LEVEL_OP); fragments = fst.concat(this.makeCode(" " + (this.invert ? '&&' : '||') + " "), shared.compileToFragments(o), this.makeCode(" " + this.operator + " "), this.second.compileToFragments(o, LEVEL_OP)); return this.wrapInBraces(fragments); }; Op.prototype.compileExistence = function(o) { var fst, ref; if (this.first.isComplex()) { ref = new Literal(o.scope.freeVariable('ref')); fst = new Parens(new Assign(ref, this.first)); } else { fst = this.first; ref = fst; } return new If(new Existence(fst), ref, { type: 'if' }).addElse(this.second).compileToFragments(o); }; Op.prototype.compileUnary = function(o) { var op, parts, plusMinus; parts = []; op = this.operator; parts.push([this.makeCode(op)]); if (op === '!' && this.first instanceof Existence) { this.first.negated = !this.first.negated; return this.first.compileToFragments(o); } if (o.level >= LEVEL_ACCESS) { return (new Parens(this)).compileToFragments(o); } plusMinus = op === '+' || op === '-'; if ((op === 'new' || op === 'typeof' || op === 'delete') || plusMinus && this.first instanceof Op && this.first.operator === op) { parts.push([this.makeCode(' ')]); } if ((plusMinus && this.first instanceof Op) || (op === 'new' && this.first.isStatement(o))) { this.first = new Parens(this.first); } parts.push(this.first.compileToFragments(o, LEVEL_OP)); if (this.flip) { parts.reverse(); } return this.joinFragmentArrays(parts, ''); }; Op.prototype.compileYield = function(o) { var op, parts; parts = []; op = this.operator; if (o.scope.parent == null) { this.error('yield statements must occur within a function generator.'); } if (indexOf.call(Object.keys(this.first), 'expression') >= 0 && !(this.first instanceof Throw)) { if (this.isYieldReturn()) { parts.push(this.first.compileToFragments(o, LEVEL_TOP)); } else if (this.first.expression != null) { parts.push(this.first.expression.compileToFragments(o, LEVEL_OP)); } } else { parts.push([this.makeCode("(" + op + " ")]); parts.push(this.first.compileToFragments(o, LEVEL_OP)); parts.push([this.makeCode(")")]); } return this.joinFragmentArrays(parts, ''); }; Op.prototype.compilePower = function(o) { var pow; pow = new Value(new Literal('Math'), [new Access(new Literal('pow'))]); return new Call(pow, [this.first, this.second]).compileToFragments(o); }; Op.prototype.compileFloorDivision = function(o) { var div, floor; floor = new Value(new Literal('Math'), [new Access(new Literal('floor'))]); div = new Op('/', this.first, this.second); return new Call(floor, [div]).compileToFragments(o); }; Op.prototype.compileModulo = function(o) { var mod; mod = new Value(new Literal(utility('modulo', o))); return new Call(mod, [this.first, this.second]).compileToFragments(o); }; Op.prototype.toString = function(idt) { return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator); }; return Op; })(Base); exports.In = In = (function(superClass1) { extend1(In, superClass1); function In(object, array) { this.object = object; this.array = array; } In.prototype.children = ['object', 'array']; In.prototype.invert = NEGATE; In.prototype.compileNode = function(o) { var hasSplat, j, len1, obj, ref3; if (this.array instanceof Value && this.array.isArray() && this.array.base.objects.length) { ref3 = this.array.base.objects; for (j = 0, len1 = ref3.length; j < len1; j++) { obj = ref3[j]; if (!(obj instanceof Splat)) { continue; } hasSplat = true; break; } if (!hasSplat) { return this.compileOrTest(o); } } return this.compileLoopTest(o); }; In.prototype.compileOrTest = function(o) { var cmp, cnj, i, item, j, len1, ref, ref3, ref4, ref5, sub, tests; ref3 = this.object.cache(o, LEVEL_OP), sub = ref3[0], ref = ref3[1]; ref4 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = ref4[0], cnj = ref4[1]; tests = []; ref5 = this.array.base.objects; for (i = j = 0, len1 = ref5.length; j < len1; i = ++j) { item = ref5[i]; if (i) { tests.push(this.makeCode(cnj)); } tests = tests.concat((i ? ref : sub), this.makeCode(cmp), item.compileToFragments(o, LEVEL_ACCESS)); } if (o.level < LEVEL_OP) { return tests; } else { return this.wrapInBraces(tests); } }; In.prototype.compileLoopTest = function(o) { var fragments, ref, ref3, sub; ref3 = this.object.cache(o, LEVEL_LIST), sub = ref3[0], ref = ref3[1]; fragments = [].concat(this.makeCode(utility('indexOf', o) + ".call("), this.array.compileToFragments(o, LEVEL_LIST), this.makeCode(", "), ref, this.makeCode(") " + (this.negated ? '< 0' : '>= 0'))); if (fragmentsToText(sub) === fragmentsToText(ref)) { return fragments; } fragments = sub.concat(this.makeCode(', '), fragments); if (o.level < LEVEL_LIST) { return fragments; } else { return this.wrapInBraces(fragments); } }; In.prototype.toString = function(idt) { return In.__super__.toString.call(this, idt, this.constructor.name + (this.negated ? '!' : '')); }; return In; })(Base); exports.Try = Try = (function(superClass1) { extend1(Try, superClass1); function Try(attempt, errorVariable, recovery, ensure) { this.attempt = attempt; this.errorVariable = errorVariable; this.recovery = recovery; this.ensure = ensure; } Try.prototype.children = ['attempt', 'recovery', 'ensure']; Try.prototype.isStatement = YES; Try.prototype.jumps = function(o) { var ref3; return this.attempt.jumps(o) || ((ref3 = this.recovery) != null ? ref3.jumps(o) : void 0); }; Try.prototype.makeReturn = function(res) { if (this.attempt) { this.attempt = this.attempt.makeReturn(res); } if (this.recovery) { this.recovery = this.recovery.makeReturn(res); } return this; }; Try.prototype.compileNode = function(o) { var catchPart, ensurePart, placeholder, tryPart; o.indent += TAB; tryPart = this.attempt.compileToFragments(o, LEVEL_TOP); catchPart = this.recovery ? (placeholder = new Literal('_error'), this.errorVariable ? this.recovery.unshift(new Assign(this.errorVariable, placeholder)) : void 0, [].concat(this.makeCode(" catch ("), placeholder.compileToFragments(o), this.makeCode(") {\n"), this.recovery.compileToFragments(o, LEVEL_TOP), this.makeCode("\n" + this.tab + "}"))) : !(this.ensure || this.recovery) ? [this.makeCode(' catch (_error) {}')] : []; ensurePart = this.ensure ? [].concat(this.makeCode(" finally {\n"), this.ensure.compileToFragments(o, LEVEL_TOP), this.makeCode("\n" + this.tab + "}")) : []; return [].concat(this.makeCode(this.tab + "try {\n"), tryPart, this.makeCode("\n" + this.tab + "}"), catchPart, ensurePart); }; return Try; })(Base); exports.Throw = Throw = (function(superClass1) { extend1(Throw, superClass1); function Throw(expression) { this.expression = expression; } Throw.prototype.children = ['expression']; Throw.prototype.isStatement = YES; Throw.prototype.jumps = NO; Throw.prototype.makeReturn = THIS; Throw.prototype.compileNode = function(o) { return [].concat(this.makeCode(this.tab + "throw "), this.expression.compileToFragments(o), this.makeCode(";")); }; return Throw; })(Base); exports.Existence = Existence = (function(superClass1) { extend1(Existence, superClass1); function Existence(expression) { this.expression = expression; } Existence.prototype.children = ['expression']; Existence.prototype.invert = NEGATE; Existence.prototype.compileNode = function(o) { var cmp, cnj, code, ref3; this.expression.front = this.front; code = this.expression.compile(o, LEVEL_OP); if (IDENTIFIER.test(code) && !o.scope.check(code)) { ref3 = this.negated ? ['===', '||'] : ['!==', '&&'], cmp = ref3[0], cnj = ref3[1]; code = "typeof " + code + " " + cmp + " \"undefined\" " + cnj + " " + code + " " + cmp + " null"; } else { code = code + " " + (this.negated ? '==' : '!=') + " null"; } return [this.makeCode(o.level <= LEVEL_COND ? code : "(" + code + ")")]; }; return Existence; })(Base); exports.Parens = Parens = (function(superClass1) { extend1(Parens, superClass1); function Parens(body1) { this.body = body1; } Parens.prototype.children = ['body']; Parens.prototype.unwrap = function() { return this.body; }; Parens.prototype.isComplex = function() { return this.body.isComplex(); }; Parens.prototype.compileNode = function(o) { var bare, expr, fragments; expr = this.body.unwrap(); if (expr instanceof Value && expr.isAtomic()) { expr.front = this.front; return expr.compileToFragments(o); } fragments = expr.compileToFragments(o, LEVEL_PAREN); bare = o.level < LEVEL_OP && (expr instanceof Op || expr instanceof Call || (expr instanceof For && expr.returns)); if (bare) { return fragments; } else { return this.wrapInBraces(fragments); } }; return Parens; })(Base); exports.For = For = (function(superClass1) { extend1(For, superClass1); function For(body, source) { var ref3; this.source = source.source, this.guard = source.guard, this.step = source.step, this.name = source.name, this.index = source.index; this.body = Block.wrap([body]); this.own = !!source.own; this.object = !!source.object; if (this.object) { ref3 = [this.index, this.name], this.name = ref3[0], this.index = ref3[1]; } if (this.index instanceof Value) { this.index.error('index cannot be a pattern matching expression'); } this.range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length; this.pattern = this.name instanceof Value; if (this.range && this.index) { this.index.error('indexes do not apply to range loops'); } if (this.range && this.pattern) { this.name.error('cannot pattern match over range loops'); } if (this.own && !this.object) { this.name.error('cannot use own with for-in'); } this.returns = false; } For.prototype.children = ['body', 'source', 'guard', 'step']; For.prototype.compileNode = function(o) { var body, bodyFragments, compare, compareDown, declare, declareDown, defPart, defPartFragments, down, forPartFragments, guardPart, idt1, increment, index, ivar, kvar, kvarAssign, last, lvar, name, namePart, ref, ref3, ref4, resultPart, returnResult, rvar, scope, source, step, stepNum, stepVar, svar, varPart; body = Block.wrap([this.body]); ref3 = body.expressions, last = ref3[ref3.length - 1]; if ((last != null ? last.jumps() : void 0) instanceof Return) { this.returns = false; } source = this.range ? this.source.base : this.source; scope = o.scope; if (!this.pattern) { name = this.name && (this.name.compile(o, LEVEL_LIST)); } index = this.index && (this.index.compile(o, LEVEL_LIST)); if (name && !this.pattern) { scope.find(name); } if (index) { scope.find(index); } if (this.returns) { rvar = scope.freeVariable('results'); } ivar = (this.object && index) || scope.freeVariable('i', { single: true }); kvar = (this.range && name) || index || ivar; kvarAssign = kvar !== ivar ? kvar + " = " : ""; if (this.step && !this.range) { ref4 = this.cacheToCodeFragments(this.step.cache(o, LEVEL_LIST, isComplexOrAssignable)), step = ref4[0], stepVar = ref4[1]; stepNum = stepVar.match(NUMBER); } if (this.pattern) { name = ivar; } varPart = ''; guardPart = ''; defPart = ''; idt1 = this.tab + TAB; if (this.range) { forPartFragments = source.compileToFragments(merge(o, { index: ivar, name: name, step: this.step, isComplex: isComplexOrAssignable })); } else { svar = this.source.compile(o, LEVEL_LIST); if ((name || this.own) && !IDENTIFIER.test(svar)) { defPart += "" + this.tab + (ref = scope.freeVariable('ref')) + " = " + svar + ";\n"; svar = ref; } if (name && !this.pattern) { namePart = name + " = " + svar + "[" + kvar + "]"; } if (!this.object) { if (step !== stepVar) { defPart += "" + this.tab + step + ";\n"; } if (!(this.step && stepNum && (down = parseNum(stepNum[0]) < 0))) { lvar = scope.freeVariable('len'); } declare = "" + kvarAssign + ivar + " = 0, " + lvar + " = " + svar + ".length"; declareDown = "" + kvarAssign + ivar + " = " + svar + ".length - 1"; compare = ivar + " < " + lvar; compareDown = ivar + " >= 0"; if (this.step) { if (stepNum) { if (down) { compare = compareDown; declare = declareDown; } } else { compare = stepVar + " > 0 ? " + compare + " : " + compareDown; declare = "(" + stepVar + " > 0 ? (" + declare + ") : " + declareDown + ")"; } increment = ivar + " += " + stepVar; } else { increment = "" + (kvar !== ivar ? "++" + ivar : ivar + "++"); } forPartFragments = [this.makeCode(declare + "; " + compare + "; " + kvarAssign + increment)]; } } if (this.returns) { resultPart = "" + this.tab + rvar + " = [];\n"; returnResult = "\n" + this.tab + "return " + rvar + ";"; body.makeReturn(rvar); } if (this.guard) { if (body.expressions.length > 1) { body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue"))); } else { if (this.guard) { body = Block.wrap([new If(this.guard, body)]); } } } if (this.pattern) { body.expressions.unshift(new Assign(this.name, new Literal(svar + "[" + kvar + "]"))); } defPartFragments = [].concat(this.makeCode(defPart), this.pluckDirectCall(o, body)); if (namePart) { varPart = "\n" + idt1 + namePart + ";"; } if (this.object) { forPartFragments = [this.makeCode(kvar + " in " + svar)]; if (this.own) { guardPart = "\n" + idt1 + "if (!" + (utility('hasProp', o)) + ".call(" + svar + ", " + kvar + ")) continue;"; } } bodyFragments = body.compileToFragments(merge(o, { indent: idt1 }), LEVEL_TOP); if (bodyFragments && (bodyFragments.length > 0)) { bodyFragments = [].concat(this.makeCode("\n"), bodyFragments, this.makeCode("\n")); } return [].concat(defPartFragments, this.makeCode("" + (resultPart || '') + this.tab + "for ("), forPartFragments, this.makeCode(") {" + guardPart + varPart), bodyFragments, this.makeCode(this.tab + "}" + (returnResult || ''))); }; For.prototype.pluckDirectCall = function(o, body) { var base, defs, expr, fn, idx, j, len1, ref, ref3, ref4, ref5, ref6, ref7, ref8, ref9, val; defs = []; ref3 = body.expressions; for (idx = j = 0, len1 = ref3.length; j < len1; idx = ++j) { expr = ref3[idx]; expr = expr.unwrapAll(); if (!(expr instanceof Call)) { continue; } val = (ref4 = expr.variable) != null ? ref4.unwrapAll() : void 0; if (!((val instanceof Code) || (val instanceof Value && ((ref5 = val.base) != null ? ref5.unwrapAll() : void 0) instanceof Code && val.properties.length === 1 && ((ref6 = (ref7 = val.properties[0].name) != null ? ref7.value : void 0) === 'call' || ref6 === 'apply')))) { continue; } fn = ((ref8 = val.base) != null ? ref8.unwrapAll() : void 0) || val; ref = new Literal(o.scope.freeVariable('fn')); base = new Value(ref); if (val.base) { ref9 = [base, val], val.base = ref9[0], base = ref9[1]; } body.expressions[idx] = new Call(base, expr.args); defs = defs.concat(this.makeCode(this.tab), new Assign(ref, fn).compileToFragments(o, LEVEL_TOP), this.makeCode(';\n')); } return defs; }; return For; })(While); exports.Switch = Switch = (function(superClass1) { extend1(Switch, superClass1); function Switch(subject, cases, otherwise) { this.subject = subject; this.cases = cases; this.otherwise = otherwise; } Switch.prototype.children = ['subject', 'cases', 'otherwise']; Switch.prototype.isStatement = YES; Switch.prototype.jumps = function(o) { var block, conds, j, jumpNode, len1, ref3, ref4, ref5; if (o == null) { o = { block: true }; } ref3 = this.cases; for (j = 0, len1 = ref3.length; j < len1; j++) { ref4 = ref3[j], conds = ref4[0], block = ref4[1]; if (jumpNode = block.jumps(o)) { return jumpNode; } } return (ref5 = this.otherwise) != null ? ref5.jumps(o) : void 0; }; Switch.prototype.makeReturn = function(res) { var j, len1, pair, ref3, ref4; ref3 = this.cases; for (j = 0, len1 = ref3.length; j < len1; j++) { pair = ref3[j]; pair[1].makeReturn(res); } if (res) { this.otherwise || (this.otherwise = new Block([new Literal('void 0')])); } if ((ref4 = this.otherwise) != null) { ref4.makeReturn(res); } return this; }; Switch.prototype.compileNode = function(o) { var block, body, cond, conditions, expr, fragments, i, idt1, idt2, j, k, len1, len2, ref3, ref4, ref5; idt1 = o.indent + TAB; idt2 = o.indent = idt1 + TAB; fragments = [].concat(this.makeCode(this.tab + "switch ("), (this.subject ? this.subject.compileToFragments(o, LEVEL_PAREN) : this.makeCode("false")), this.makeCode(") {\n")); ref3 = this.cases; for (i = j = 0, len1 = ref3.length; j < len1; i = ++j) { ref4 = ref3[i], conditions = ref4[0], block = ref4[1]; ref5 = flatten([conditions]); for (k = 0, len2 = ref5.length; k < len2; k++) { cond = ref5[k]; if (!this.subject) { cond = cond.invert(); } fragments = fragments.concat(this.makeCode(idt1 + "case "), cond.compileToFragments(o, LEVEL_PAREN), this.makeCode(":\n")); } if ((body = block.compileToFragments(o, LEVEL_TOP)).length > 0) { fragments = fragments.concat(body, this.makeCode('\n')); } if (i === this.cases.length - 1 && !this.otherwise) { break; } expr = this.lastNonComment(block.expressions); if (expr instanceof Return || (expr instanceof Literal && expr.jumps() && expr.value !== 'debugger')) { continue; } fragments.push(cond.makeCode(idt2 + 'break;\n')); } if (this.otherwise && this.otherwise.expressions.length) { fragments.push.apply(fragments, [this.makeCode(idt1 + "default:\n")].concat(slice.call(this.otherwise.compileToFragments(o, LEVEL_TOP)), [this.makeCode("\n")])); } fragments.push(this.makeCode(this.tab + '}')); return fragments; }; return Switch; })(Base); exports.If = If = (function(superClass1) { extend1(If, superClass1); function If(condition, body1, options) { this.body = body1; if (options == null) { options = {}; } this.condition = options.type === 'unless' ? condition.invert() : condition; this.elseBody = null; this.isChain = false; this.soak = options.soak; } If.prototype.children = ['condition', 'body', 'elseBody']; If.prototype.bodyNode = function() { var ref3; return (ref3 = this.body) != null ? ref3.unwrap() : void 0; }; If.prototype.elseBodyNode = function() { var ref3; return (ref3 = this.elseBody) != null ? ref3.unwrap() : void 0; }; If.prototype.addElse = function(elseBody) { if (this.isChain) { this.elseBodyNode().addElse(elseBody); } else { this.isChain = elseBody instanceof If; this.elseBody = this.ensureBlock(elseBody); this.elseBody.updateLocationDataIfMissing(elseBody.locationData); } return this; }; If.prototype.isStatement = function(o) { var ref3; return (o != null ? o.level : void 0) === LEVEL_TOP || this.bodyNode().isStatement(o) || ((ref3 = this.elseBodyNode()) != null ? ref3.isStatement(o) : void 0); }; If.prototype.jumps = function(o) { var ref3; return this.body.jumps(o) || ((ref3 = this.elseBody) != null ? ref3.jumps(o) : void 0); }; If.prototype.compileNode = function(o) { if (this.isStatement(o)) { return this.compileStatement(o); } else { return this.compileExpression(o); } }; If.prototype.makeReturn = function(res) { if (res) { this.elseBody || (this.elseBody = new Block([new Literal('void 0')])); } this.body && (this.body = new Block([this.body.makeReturn(res)])); this.elseBody && (this.elseBody = new Block([this.elseBody.makeReturn(res)])); return this; }; If.prototype.ensureBlock = function(node) { if (node instanceof Block) { return node; } else { return new Block([node]); } }; If.prototype.compileStatement = function(o) { var answer, body, child, cond, exeq, ifPart, indent; child = del(o, 'chainChild'); exeq = del(o, 'isExistentialEquals'); if (exeq) { return new If(this.condition.invert(), this.elseBodyNode(), { type: 'if' }).compileToFragments(o); } indent = o.indent + TAB; cond = this.condition.compileToFragments(o, LEVEL_PAREN); body = this.ensureBlock(this.body).compileToFragments(merge(o, { indent: indent })); ifPart = [].concat(this.makeCode("if ("), cond, this.makeCode(") {\n"), body, this.makeCode("\n" + this.tab + "}")); if (!child) { ifPart.unshift(this.makeCode(this.tab)); } if (!this.elseBody) { return ifPart; } answer = ifPart.concat(this.makeCode(' else ')); if (this.isChain) { o.chainChild = true; answer = answer.concat(this.elseBody.unwrap().compileToFragments(o, LEVEL_TOP)); } else { answer = answer.concat(this.makeCode("{\n"), this.elseBody.compileToFragments(merge(o, { indent: indent }), LEVEL_TOP), this.makeCode("\n" + this.tab + "}")); } return answer; }; If.prototype.compileExpression = function(o) { var alt, body, cond, fragments; cond = this.condition.compileToFragments(o, LEVEL_COND); body = this.bodyNode().compileToFragments(o, LEVEL_LIST); alt = this.elseBodyNode() ? this.elseBodyNode().compileToFragments(o, LEVEL_LIST) : [this.makeCode('void 0')]; fragments = cond.concat(this.makeCode(" ? "), body, this.makeCode(" : "), alt); if (o.level >= LEVEL_COND) { return this.wrapInBraces(fragments); } else { return fragments; } }; If.prototype.unfoldSoak = function() { return this.soak && this; }; return If; })(Base); UTILITIES = { extend: function(o) { return "function(child, parent) { for (var key in parent) { if (" + (utility('hasProp', o)) + ".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; }"; }, bind: function() { return 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }'; }, indexOf: function() { return "[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }"; }, modulo: function() { return "function(a, b) { return (+a % (b = +b) + b) % b; }"; }, hasProp: function() { return '{}.hasOwnProperty'; }, slice: function() { return '[].slice'; } }; LEVEL_TOP = 1; LEVEL_PAREN = 2; LEVEL_LIST = 3; LEVEL_COND = 4; LEVEL_OP = 5; LEVEL_ACCESS = 6; TAB = ' '; IDENTIFIER = /^(?!\d)[$\w\x7f-\uffff]+$/; SIMPLENUM = /^[+-]?\d+$/; HEXNUM = /^[+-]?0x[\da-f]+/i; NUMBER = /^[+-]?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)$/i; IS_STRING = /^['"]/; IS_REGEX = /^\//; utility = function(name, o) { var ref, root; root = o.scope.root; if (name in root.utilities) { return root.utilities[name]; } else { ref = root.freeVariable(name); root.assign(ref, UTILITIES[name](o)); return root.utilities[name] = ref; } }; multident = function(code, tab) { code = code.replace(/\n/g, '$&' + tab); return code.replace(/\s+$/, ''); }; parseNum = function(x) { if (x == null) { return 0; } else if (x.match(HEXNUM)) { return parseInt(x, 16); } else { return parseFloat(x); } }; isLiteralArguments = function(node) { return node instanceof Literal && node.value === 'arguments' && !node.asKey; }; isLiteralThis = function(node) { return (node instanceof Literal && node.value === 'this' && !node.asKey) || (node instanceof Code && node.bound) || (node instanceof Call && node.isSuper); }; isComplexOrAssignable = function(node) { return node.isComplex() || (typeof node.isAssignable === "function" ? node.isAssignable() : void 0); }; unfoldSoak = function(o, parent, name) { var ifn; if (!(ifn = parent[name].unfoldSoak(o))) { return; } parent[name] = ifn.body; ifn.body = new Value(parent); return ifn; }; }).call(this); 1.9.3~dfsg/lib/coffee-script/scope.js0000644000000000000000000001003212531364553016237 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { 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) { var ref, ref1; this.parent = parent; this.expressions = expressions; this.method = method; this.referencedVars = referencedVars; this.variables = [ { name: 'arguments', type: 'arguments' } ]; this.positions = {}; if (!this.parent) { this.utilities = {}; } this.root = (ref = (ref1 = this.parent) != null ? ref1.root : void 0) != null ? ref : this; } Scope.prototype.add = function(name, type, immediate) { if (this.shared && !immediate) { return this.parent.add(name, type, immediate); } if (Object.prototype.hasOwnProperty.call(this.positions, name)) { return this.variables[this.positions[name]].type = type; } else { return this.positions[name] = this.variables.push({ name: name, type: type }) - 1; } }; Scope.prototype.namedMethod = function() { 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) { if (this.check(name)) { return true; } this.add(name, 'var'); return false; }; Scope.prototype.parameter = function(name) { if (this.shared && this.parent.check(name, true)) { return; } return this.add(name, 'param'); }; Scope.prototype.check = function(name) { var ref; return !!(this.type(name) || ((ref = this.parent) != null ? ref.check(name) : void 0)); }; Scope.prototype.temporary = function(name, index, single) { if (single == null) { single = false; } if (single) { return (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a'); } else { return name + (index || ''); } }; Scope.prototype.type = function(name) { var i, len, ref, v; ref = this.variables; for (i = 0, len = ref.length; i < len; i++) { v = ref[i]; if (v.name === name) { return v.type; } } return null; }; Scope.prototype.freeVariable = function(name, options) { var index, ref, temp; if (options == null) { options = {}; } index = 0; while (true) { temp = this.temporary(name, index, options.single); if (!(this.check(temp) || indexOf.call(this.root.referencedVars, temp) >= 0)) { break; } index++; } if ((ref = options.reserve) != null ? ref : true) { this.add(temp, 'var', true); } return temp; }; Scope.prototype.assign = function(name, value) { this.add(name, { value: value, assigned: true }, true); return this.hasAssignments = true; }; Scope.prototype.hasDeclarations = function() { return !!this.declaredVariables().length; }; Scope.prototype.declaredVariables = function() { var v; return ((function() { var i, len, ref, results; ref = this.variables; results = []; for (i = 0, len = ref.length; i < len; i++) { v = ref[i]; if (v.type === 'var') { results.push(v.name); } } return results; }).call(this)).sort(); }; Scope.prototype.assignedVariables = function() { var i, len, ref, results, v; ref = this.variables; results = []; for (i = 0, len = ref.length; i < len; i++) { v = ref[i]; if (v.type.assigned) { results.push(v.name + " = " + v.type.value); } } return results; }; return Scope; })(); }).call(this); 1.9.3~dfsg/lib/coffee-script/command.js0000644000000000000000000004413012531364553016552 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, findDirectoryIndex, forkNode, fs, helpers, hidden, joinTimeout, makePrelude, mkdirp, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, ref, removeSource, removeSourceDir, silentUnlink, sourceCode, sources, spawn, timeLog, usage, useWinPathSep, version, wait, watch, watchDir, watchedDirs, writeJs, 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; }; fs = require('fs'); path = require('path'); helpers = require('./helpers'); optparse = require('./optparse'); CoffeeScript = require('./coffee-script'); ref = require('child_process'), spawn = ref.spawn, exec = ref.exec; EventEmitter = require('events').EventEmitter; useWinPathSep = path.sep === '\\'; helpers.extend(CoffeeScript, new EventEmitter); printLine = function(line) { return process.stdout.write(line + '\n'); }; printWarn = function(line) { return process.stderr.write(line + '\n'); }; hidden = function(file) { return /^\.|~$/.test(file); }; BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.'; SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-m', '--map', 'generate source map and save as .js.map files'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['--no-header', 'suppress the "Generated by" header'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [MODULE*]', 'require the given module before eval or REPL'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-l', '--literate', 'treat stdio as literate style coffee-script'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']]; opts = {}; sources = []; sourceCode = []; notSources = {}; watchedDirs = {}; optionParser = null; exports.run = function() { var i, len, literals, ref1, replCliOpts, results, source; parseOptions(); replCliOpts = { useGlobal: true }; if (opts.require) { opts.prelude = makePrelude(opts.require); } replCliOpts.prelude = opts.prelude; if (opts.nodejs) { return forkNode(); } if (opts.help) { return usage(); } if (opts.version) { return version(); } if (opts.interactive) { return require('./repl').start(replCliOpts); } if (opts.stdio) { return compileStdio(); } if (opts["eval"]) { return compileScript(null, opts["arguments"][0]); } if (!opts["arguments"].length) { return require('./repl').start(replCliOpts); } literals = opts.run ? opts["arguments"].splice(1) : []; process.argv = process.argv.slice(0, 2).concat(literals); process.argv[0] = 'coffee'; if (opts.output) { opts.output = path.resolve(opts.output); } if (opts.join) { opts.join = path.resolve(opts.join); console.error('\nThe --join option is deprecated and will be removed in a future version.\n\nIf for some reason it\'s necessary to share local variables between files,\nreplace...\n\n $ coffee --compile --join bundle.js -- a.coffee b.coffee c.coffee\n\nwith...\n\n $ cat a.coffee b.coffee c.coffee | coffee --compile --stdio > bundle.js\n'); } ref1 = opts["arguments"]; results = []; for (i = 0, len = ref1.length; i < len; i++) { source = ref1[i]; source = path.resolve(source); results.push(compilePath(source, true, source)); } return results; }; makePrelude = function(requires) { return requires.map(function(module) { var _, match, name; if (match = module.match(/^(.*)=(.*)$/)) { _ = match[0], name = match[1], module = match[2]; } name || (name = helpers.baseFileName(module, true, useWinPathSep)); return name + " = require('" + module + "')"; }).join(';'); }; compilePath = function(source, topLevel, base) { var code, err, file, files, i, len, results, stats; if (indexOf.call(sources, source) >= 0 || watchedDirs[source] || !topLevel && (notSources[source] || hidden(source))) { return; } try { stats = fs.statSync(source); } catch (_error) { err = _error; if (err.code === 'ENOENT') { console.error("File not found: " + source); process.exit(1); } throw err; } if (stats.isDirectory()) { if (path.basename(source) === 'node_modules') { notSources[source] = true; return; } if (opts.run) { compilePath(findDirectoryIndex(source), topLevel, base); return; } if (opts.watch) { watchDir(source, base); } try { files = fs.readdirSync(source); } catch (_error) { err = _error; if (err.code === 'ENOENT') { return; } else { throw err; } } results = []; for (i = 0, len = files.length; i < len; i++) { file = files[i]; results.push(compilePath(path.join(source, file), false, base)); } return results; } else if (topLevel || helpers.isCoffee(source)) { sources.push(source); sourceCode.push(null); delete notSources[source]; if (opts.watch) { watch(source, base); } try { code = fs.readFileSync(source); } catch (_error) { err = _error; if (err.code === 'ENOENT') { return; } else { throw err; } } return compileScript(source, code.toString(), base); } else { return notSources[source] = true; } }; findDirectoryIndex = function(source) { var err, ext, i, index, len, ref1; ref1 = CoffeeScript.FILE_EXTENSIONS; for (i = 0, len = ref1.length; i < len; i++) { ext = ref1[i]; index = path.join(source, "index" + ext); try { if ((fs.statSync(index)).isFile()) { return index; } } catch (_error) { err = _error; if (err.code !== 'ENOENT') { throw err; } } } console.error("Missing index.coffee or index.litcoffee in " + source); return process.exit(1); }; compileScript = function(file, input, base) { var compiled, err, message, o, options, t, task; if (base == null) { base = null; } o = opts; options = compileOptions(file, base); try { t = task = { file: file, input: input, options: options }; CoffeeScript.emit('compile', task); if (o.tokens) { return printTokens(CoffeeScript.tokens(t.input, t.options)); } else if (o.nodes) { return printLine(CoffeeScript.nodes(t.input, t.options).toString().trim()); } else if (o.run) { CoffeeScript.register(); if (opts.prelude) { CoffeeScript["eval"](opts.prelude, t.options); } return CoffeeScript.run(t.input, t.options); } else if (o.join && t.file !== o.join) { if (helpers.isLiterate(file)) { t.input = helpers.invertLiterate(t.input); } sourceCode[sources.indexOf(t.file)] = t.input; return compileJoin(); } else { compiled = CoffeeScript.compile(t.input, t.options); t.output = compiled; if (o.map) { t.output = compiled.js; t.sourceMap = compiled.v3SourceMap; } CoffeeScript.emit('success', task); if (o.print) { return printLine(t.output.trim()); } else if (o.compile || o.map) { return writeJs(base, t.file, t.output, options.jsPath, t.sourceMap); } } } catch (_error) { err = _error; CoffeeScript.emit('failure', err, task); if (CoffeeScript.listeners('failure').length) { return; } message = err.stack || ("" + err); if (o.watch) { return printLine(message + '\x07'); } else { printWarn(message); return process.exit(1); } } }; compileStdio = function() { var code, stdin; code = ''; stdin = process.openStdin(); stdin.on('data', function(buffer) { if (buffer) { return code += buffer.toString(); } }); return stdin.on('end', function() { return compileScript(null, code); }); }; joinTimeout = null; compileJoin = function() { if (!opts.join) { return; } if (!sourceCode.some(function(code) { return code === null; })) { clearTimeout(joinTimeout); return joinTimeout = wait(100, function() { return compileScript(opts.join, sourceCode.join('\n'), opts.join); }); } }; watch = function(source, base) { var compile, compileTimeout, err, prevStats, rewatch, startWatcher, watchErr, watcher; watcher = null; prevStats = null; compileTimeout = null; watchErr = function(err) { if (err.code !== 'ENOENT') { throw err; } if (indexOf.call(sources, source) < 0) { return; } try { rewatch(); return compile(); } catch (_error) { removeSource(source, base); return compileJoin(); } }; compile = function() { clearTimeout(compileTimeout); return compileTimeout = wait(25, function() { return fs.stat(source, function(err, stats) { if (err) { return watchErr(err); } if (prevStats && stats.size === prevStats.size && stats.mtime.getTime() === prevStats.mtime.getTime()) { return rewatch(); } prevStats = stats; return fs.readFile(source, function(err, code) { if (err) { return watchErr(err); } compileScript(source, code.toString(), base); return rewatch(); }); }); }); }; startWatcher = function() { return watcher = fs.watch(source).on('change', compile).on('error', function(err) { if (err.code !== 'EPERM') { throw err; } return removeSource(source, base); }); }; rewatch = function() { if (watcher != null) { watcher.close(); } return startWatcher(); }; try { return startWatcher(); } catch (_error) { err = _error; return watchErr(err); } }; watchDir = function(source, base) { var err, readdirTimeout, startWatcher, stopWatcher, watcher; watcher = null; readdirTimeout = null; startWatcher = function() { return watcher = fs.watch(source).on('error', function(err) { if (err.code !== 'EPERM') { throw err; } return stopWatcher(); }).on('change', function() { clearTimeout(readdirTimeout); return readdirTimeout = wait(25, function() { var err, file, files, i, len, results; try { files = fs.readdirSync(source); } catch (_error) { err = _error; if (err.code !== 'ENOENT') { throw err; } return stopWatcher(); } results = []; for (i = 0, len = files.length; i < len; i++) { file = files[i]; results.push(compilePath(path.join(source, file), false, base)); } return results; }); }); }; stopWatcher = function() { watcher.close(); return removeSourceDir(source, base); }; watchedDirs[source] = true; try { return startWatcher(); } catch (_error) { err = _error; if (err.code !== 'ENOENT') { throw err; } } }; removeSourceDir = function(source, base) { var file, i, len, sourcesChanged; delete watchedDirs[source]; sourcesChanged = false; for (i = 0, len = sources.length; i < len; i++) { file = sources[i]; if (!(source === path.dirname(file))) { continue; } removeSource(file, base); sourcesChanged = true; } if (sourcesChanged) { return compileJoin(); } }; removeSource = function(source, base) { var index; index = sources.indexOf(source); sources.splice(index, 1); sourceCode.splice(index, 1); if (!opts.join) { silentUnlink(outputPath(source, base)); silentUnlink(outputPath(source, base, '.js.map')); return timeLog("removed " + source); } }; silentUnlink = function(path) { var err, ref1; try { return fs.unlinkSync(path); } catch (_error) { err = _error; if ((ref1 = err.code) !== 'ENOENT' && ref1 !== 'EPERM') { throw err; } } }; outputPath = function(source, base, extension) { var basename, dir, srcDir; if (extension == null) { extension = ".js"; } basename = helpers.baseFileName(source, true, useWinPathSep); srcDir = path.dirname(source); if (!opts.output) { dir = srcDir; } else if (source === base) { dir = opts.output; } else { dir = path.join(opts.output, path.relative(base, srcDir)); } return path.join(dir, basename + extension); }; mkdirp = function(dir, fn) { var mkdirs, mode; mode = 0x1ff & ~process.umask(); return (mkdirs = function(p, fn) { return fs.exists(p, function(exists) { if (exists) { return fn(); } else { return mkdirs(path.dirname(p), function() { return fs.mkdir(p, mode, function(err) { if (err) { return fn(err); } return fn(); }); }); } }); })(dir, fn); }; writeJs = function(base, sourcePath, js, jsPath, generatedSourceMap) { var compile, jsDir, sourceMapPath; if (generatedSourceMap == null) { generatedSourceMap = null; } sourceMapPath = outputPath(sourcePath, base, ".js.map"); jsDir = path.dirname(jsPath); compile = function() { if (opts.compile) { if (js.length <= 0) { js = ' '; } if (generatedSourceMap) { js = js + "\n//# sourceMappingURL=" + (helpers.baseFileName(sourceMapPath, false, useWinPathSep)) + "\n"; } fs.writeFile(jsPath, js, function(err) { if (err) { printLine(err.message); return process.exit(1); } else if (opts.compile && opts.watch) { return timeLog("compiled " + sourcePath); } }); } if (generatedSourceMap) { return fs.writeFile(sourceMapPath, generatedSourceMap, function(err) { if (err) { printLine("Could not write source map: " + err.message); return process.exit(1); } }); } }; return fs.exists(jsDir, function(itExists) { if (itExists) { return compile(); } else { return mkdirp(jsDir, compile); } }); }; wait = function(milliseconds, func) { return setTimeout(func, milliseconds); }; timeLog = function(message) { return console.log(((new Date).toLocaleTimeString()) + " - " + message); }; printTokens = function(tokens) { var strings, tag, token, value; strings = (function() { var i, len, results; results = []; for (i = 0, len = tokens.length; i < len; i++) { token = tokens[i]; tag = token[0]; value = token[1].toString().replace(/\n/, '\\n'); results.push("[" + tag + " " + value + "]"); } return results; })(); return printLine(strings.join(' ')); }; parseOptions = function() { var o; optionParser = new optparse.OptionParser(SWITCHES, BANNER); o = opts = optionParser.parse(process.argv.slice(2)); o.compile || (o.compile = !!o.output); o.run = !(o.compile || o.print || o.map); return o.print = !!(o.print || (o["eval"] || o.stdio && o.compile)); }; compileOptions = function(filename, base) { var answer, cwd, jsDir, jsPath; answer = { filename: filename, literate: opts.literate || helpers.isLiterate(filename), bare: opts.bare, header: opts.compile && !opts['no-header'], sourceMap: opts.map }; if (filename) { if (base) { cwd = process.cwd(); jsPath = outputPath(filename, base); jsDir = path.dirname(jsPath); answer = helpers.merge(answer, { jsPath: jsPath, sourceRoot: path.relative(jsDir, cwd), sourceFiles: [path.relative(cwd, filename)], generatedFile: helpers.baseFileName(jsPath, false, useWinPathSep) }); } else { answer = helpers.merge(answer, { sourceRoot: "", sourceFiles: [helpers.baseFileName(filename, false, useWinPathSep)], generatedFile: helpers.baseFileName(filename, true, useWinPathSep) + ".js" }); } } return answer; }; forkNode = function() { var args, nodeArgs, p; nodeArgs = opts.nodejs.split(/\s+/); args = process.argv.slice(1); args.splice(args.indexOf('--nodejs'), 2); p = spawn(process.execPath, nodeArgs.concat(args), { cwd: process.cwd(), env: process.env, stdio: [0, 1, 2] }); return p.on('exit', function(code) { return process.exit(code); }); }; usage = function() { return printLine((new optparse.OptionParser(SWITCHES, BANNER)).help()); }; version = function() { return printLine("CoffeeScript version " + CoffeeScript.VERSION); }; }).call(this); 1.9.3~dfsg/lib/coffee-script/browser.js0000644000000000000000000000775412531364553016632 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var CoffeeScript, compile, runScripts, 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; }; CoffeeScript = require('./coffee-script'); CoffeeScript.require = require; compile = CoffeeScript.compile; CoffeeScript["eval"] = function(code, options) { if (options == null) { options = {}; } if (options.bare == null) { options.bare = true; } return eval(compile(code, options)); }; CoffeeScript.run = function(code, options) { if (options == null) { options = {}; } options.bare = true; options.shiftLine = true; return Function(compile(code, options))(); }; if (typeof window === "undefined" || window === null) { return; } if ((typeof btoa !== "undefined" && btoa !== null) && (typeof JSON !== "undefined" && JSON !== null) && (typeof unescape !== "undefined" && unescape !== null) && (typeof encodeURIComponent !== "undefined" && encodeURIComponent !== null)) { compile = function(code, options) { var js, ref, v3SourceMap; if (options == null) { options = {}; } options.sourceMap = true; options.inline = true; ref = CoffeeScript.compile(code, options), js = ref.js, v3SourceMap = ref.v3SourceMap; return js + "\n//# sourceMappingURL=data:application/json;base64," + (btoa(unescape(encodeURIComponent(v3SourceMap)))) + "\n//# sourceURL=coffeescript"; }; } CoffeeScript.load = function(url, callback, options, hold) { var xhr; if (options == null) { options = {}; } if (hold == null) { hold = false; } options.sourceFiles = [url]; xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') : new window.XMLHttpRequest(); xhr.open('GET', url, true); if ('overrideMimeType' in xhr) { xhr.overrideMimeType('text/plain'); } xhr.onreadystatechange = function() { var param, ref; if (xhr.readyState === 4) { if ((ref = xhr.status) === 0 || ref === 200) { param = [xhr.responseText, options]; if (!hold) { CoffeeScript.run.apply(CoffeeScript, param); } } else { throw new Error("Could not load " + url); } if (callback) { return callback(param); } } }; return xhr.send(null); }; runScripts = function() { var coffees, coffeetypes, execute, fn, i, index, j, len, s, script, scripts; scripts = window.document.getElementsByTagName('script'); coffeetypes = ['text/coffeescript', 'text/literate-coffeescript']; coffees = (function() { var j, len, ref, results; results = []; for (j = 0, len = scripts.length; j < len; j++) { s = scripts[j]; if (ref = s.type, indexOf.call(coffeetypes, ref) >= 0) { results.push(s); } } return results; })(); index = 0; execute = function() { var param; param = coffees[index]; if (param instanceof Array) { CoffeeScript.run.apply(CoffeeScript, param); index++; return execute(); } }; fn = function(script, i) { var options, source; options = { literate: script.type === coffeetypes[1] }; source = script.src || script.getAttribute('data-src'); if (source) { return CoffeeScript.load(source, function(param) { coffees[i] = param; return execute(); }, options, true); } else { options.sourceFiles = ['embedded']; return coffees[i] = [script.innerHTML, options]; } }; for (i = j = 0, len = coffees.length; j < len; i = ++j) { script = coffees[i]; fn(script, i); } return execute(); }; if (window.addEventListener) { window.addEventListener('DOMContentLoaded', runScripts, false); } else { window.attachEvent('onload', runScripts); } }).call(this); 1.9.3~dfsg/lib/coffee-script/grammar.js0000644000000000000000000004746412531364553016577 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap; Parser = require('jison').Parser; unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/; o = function(patternString, action, options) { var addLocationDataFn, match, patternCount; patternString = patternString.replace(/\s{2,}/g, ' '); patternCount = patternString.split(' ').length; if (!action) { return [patternString, '$$ = $1;', options]; } action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())"; action = action.replace(/\bnew /g, '$&yy.'); action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&'); addLocationDataFn = function(first, last) { if (!last) { return "yy.addLocationDataFn(@" + first + ")"; } else { return "yy.addLocationDataFn(@" + first + ", @" + last + ")"; } }; action = action.replace(/LOC\(([0-9]*)\)/g, addLocationDataFn('$1')); action = action.replace(/LOC\(([0-9]*),\s*([0-9]*)\)/g, addLocationDataFn('$1', '$2')); return [patternString, "$$ = " + (addLocationDataFn(1, patternCount)) + "(" + action + ");", options]; }; grammar = { Root: [ o('', function() { return new Block; }), o('Body') ], Body: [ o('Line', function() { return Block.wrap([$1]); }), o('Body TERMINATOR Line', function() { return $1.push($3); }), o('Body TERMINATOR') ], Line: [o('Expression'), o('Statement')], Statement: [ o('Return'), o('Comment'), o('STATEMENT', function() { return new Literal($1); }) ], Expression: [o('Value'), o('Invocation'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class'), o('Throw')], Block: [ o('INDENT OUTDENT', function() { return new Block; }), o('INDENT Body OUTDENT', function() { return $2; }) ], Identifier: [ o('IDENTIFIER', function() { return new Literal($1); }) ], AlphaNumeric: [ o('NUMBER', function() { return new Literal($1); }), o('String') ], String: [ o('STRING', function() { return new Literal($1); }), o('STRING_START Body STRING_END', function() { return new Parens($2); }) ], Regex: [ o('REGEX', function() { return new Literal($1); }), o('REGEX_START Invocation REGEX_END', function() { return $2; }) ], Literal: [ o('AlphaNumeric'), o('JS', function() { return new Literal($1); }), o('Regex'), o('DEBUGGER', function() { return new Literal($1); }), o('UNDEFINED', function() { return new Undefined; }), o('NULL', function() { return new Null; }), o('BOOL', function() { return new Bool($1); }) ], Assign: [ o('Assignable = Expression', function() { return new Assign($1, $3); }), o('Assignable = TERMINATOR Expression', function() { return new Assign($1, $4); }), o('Assignable = INDENT Expression OUTDENT', function() { return new Assign($1, $4); }) ], AssignObj: [ o('ObjAssignable', function() { return new Value($1); }), o('ObjAssignable : Expression', function() { return new Assign(LOC(1)(new Value($1)), $3, 'object'); }), o('ObjAssignable : INDENT Expression OUTDENT', function() { return new Assign(LOC(1)(new Value($1)), $4, 'object'); }), o('Comment') ], ObjAssignable: [o('Identifier'), o('AlphaNumeric'), o('ThisProperty')], Return: [ o('RETURN Expression', function() { return new Return($2); }), o('RETURN', function() { return new Return; }) ], Comment: [ o('HERECOMMENT', function() { return new Comment($1); }) ], Code: [ o('PARAM_START ParamList PARAM_END FuncGlyph Block', function() { return new Code($2, $5, $4); }), o('FuncGlyph Block', function() { return new Code([], $2, $1); }) ], FuncGlyph: [ o('->', function() { return 'func'; }), o('=>', function() { return 'boundfunc'; }) ], OptComma: [o(''), o(',')], ParamList: [ o('', function() { return []; }), o('Param', function() { return [$1]; }), o('ParamList , Param', function() { return $1.concat($3); }), o('ParamList OptComma TERMINATOR Param', function() { return $1.concat($4); }), o('ParamList OptComma INDENT ParamList OptComma OUTDENT', function() { return $1.concat($4); }) ], Param: [ o('ParamVar', function() { return new Param($1); }), o('ParamVar ...', function() { return new Param($1, null, true); }), o('ParamVar = Expression', function() { return new Param($1, $3); }), o('...', function() { return new Expansion; }) ], ParamVar: [o('Identifier'), o('ThisProperty'), o('Array'), o('Object')], Splat: [ o('Expression ...', function() { return new Splat($1); }) ], SimpleAssignable: [ o('Identifier', function() { return new Value($1); }), o('Value Accessor', function() { return $1.add($2); }), o('Invocation Accessor', function() { return new Value($1, [].concat($2)); }), o('ThisProperty') ], Assignable: [ o('SimpleAssignable'), o('Array', function() { return new Value($1); }), o('Object', function() { return new Value($1); }) ], Value: [ o('Assignable'), o('Literal', function() { return new Value($1); }), o('Parenthetical', function() { return new Value($1); }), o('Range', function() { return new Value($1); }), o('This') ], Accessor: [ o('. Identifier', function() { return new Access($2); }), o('?. Identifier', function() { return new Access($2, 'soak'); }), o(':: Identifier', function() { return [LOC(1)(new Access(new Literal('prototype'))), LOC(2)(new Access($2))]; }), o('?:: Identifier', function() { return [LOC(1)(new Access(new Literal('prototype'), 'soak')), LOC(2)(new Access($2))]; }), o('::', function() { return new Access(new Literal('prototype')); }), o('Index') ], Index: [ o('INDEX_START IndexValue INDEX_END', function() { return $2; }), o('INDEX_SOAK Index', function() { return extend($2, { soak: true }); }) ], IndexValue: [ o('Expression', function() { return new Index($1); }), o('Slice', function() { return new Slice($1); }) ], Object: [ o('{ AssignList OptComma }', function() { return new Obj($2, $1.generated); }) ], AssignList: [ o('', function() { return []; }), o('AssignObj', function() { return [$1]; }), o('AssignList , AssignObj', function() { return $1.concat($3); }), o('AssignList OptComma TERMINATOR AssignObj', function() { return $1.concat($4); }), o('AssignList OptComma INDENT AssignList OptComma OUTDENT', function() { return $1.concat($4); }) ], Class: [ o('CLASS', function() { return new Class; }), o('CLASS Block', function() { return new Class(null, null, $2); }), o('CLASS EXTENDS Expression', function() { return new Class(null, $3); }), o('CLASS EXTENDS Expression Block', function() { return new Class(null, $3, $4); }), o('CLASS SimpleAssignable', function() { return new Class($2); }), o('CLASS SimpleAssignable Block', function() { return new Class($2, null, $3); }), o('CLASS SimpleAssignable EXTENDS Expression', function() { return new Class($2, $4); }), o('CLASS SimpleAssignable EXTENDS Expression Block', function() { return new Class($2, $4, $5); }) ], Invocation: [ o('Value OptFuncExist Arguments', function() { return new Call($1, $3, $2); }), o('Invocation OptFuncExist Arguments', function() { return new Call($1, $3, $2); }), o('SUPER', function() { return new Call('super', [new Splat(new Literal('arguments'))]); }), o('SUPER Arguments', function() { return new Call('super', $2); }) ], OptFuncExist: [ o('', function() { return false; }), o('FUNC_EXIST', function() { return true; }) ], Arguments: [ o('CALL_START CALL_END', function() { return []; }), o('CALL_START ArgList OptComma CALL_END', function() { return $2; }) ], This: [ o('THIS', function() { return new Value(new Literal('this')); }), o('@', function() { return new Value(new Literal('this')); }) ], ThisProperty: [ o('@ Identifier', function() { return new Value(LOC(1)(new Literal('this')), [LOC(2)(new Access($2))], 'this'); }) ], Array: [ o('[ ]', function() { return new Arr([]); }), o('[ ArgList OptComma ]', function() { return new Arr($2); }) ], RangeDots: [ o('..', function() { return 'inclusive'; }), o('...', function() { return 'exclusive'; }) ], Range: [ o('[ Expression RangeDots Expression ]', function() { return new Range($2, $4, $3); }) ], Slice: [ o('Expression RangeDots Expression', function() { return new Range($1, $3, $2); }), o('Expression RangeDots', function() { return new Range($1, null, $2); }), o('RangeDots Expression', function() { return new Range(null, $2, $1); }), o('RangeDots', function() { return new Range(null, null, $1); }) ], ArgList: [ o('Arg', function() { return [$1]; }), o('ArgList , Arg', function() { return $1.concat($3); }), o('ArgList OptComma TERMINATOR Arg', function() { return $1.concat($4); }), o('INDENT ArgList OptComma OUTDENT', function() { return $2; }), o('ArgList OptComma INDENT ArgList OptComma OUTDENT', function() { return $1.concat($4); }) ], Arg: [ o('Expression'), o('Splat'), o('...', function() { return new Expansion; }) ], SimpleArgs: [ o('Expression'), o('SimpleArgs , Expression', function() { return [].concat($1, $3); }) ], Try: [ o('TRY Block', function() { return new Try($2); }), o('TRY Block Catch', function() { return new Try($2, $3[0], $3[1]); }), o('TRY Block FINALLY Block', function() { return new Try($2, null, null, $4); }), o('TRY Block Catch FINALLY Block', function() { return new Try($2, $3[0], $3[1], $5); }) ], Catch: [ o('CATCH Identifier Block', function() { return [$2, $3]; }), o('CATCH Object Block', function() { return [LOC(2)(new Value($2)), $3]; }), o('CATCH Block', function() { return [null, $2]; }) ], Throw: [ o('THROW Expression', function() { return new Throw($2); }) ], Parenthetical: [ o('( Body )', function() { return new Parens($2); }), o('( INDENT Body OUTDENT )', function() { return new Parens($3); }) ], WhileSource: [ o('WHILE Expression', function() { return new While($2); }), o('WHILE Expression WHEN Expression', function() { return new While($2, { guard: $4 }); }), o('UNTIL Expression', function() { return new While($2, { invert: true }); }), o('UNTIL Expression WHEN Expression', function() { return new While($2, { invert: true, guard: $4 }); }) ], While: [ o('WhileSource Block', function() { return $1.addBody($2); }), o('Statement WhileSource', function() { return $2.addBody(LOC(1)(Block.wrap([$1]))); }), o('Expression WhileSource', function() { return $2.addBody(LOC(1)(Block.wrap([$1]))); }), o('Loop', function() { return $1; }) ], Loop: [ o('LOOP Block', function() { return new While(LOC(1)(new Literal('true'))).addBody($2); }), o('LOOP Expression', function() { return new While(LOC(1)(new Literal('true'))).addBody(LOC(2)(Block.wrap([$2]))); }) ], For: [ o('Statement ForBody', function() { return new For($1, $2); }), o('Expression ForBody', function() { return new For($1, $2); }), o('ForBody Block', function() { return new For($2, $1); }) ], ForBody: [ o('FOR Range', function() { return { source: LOC(2)(new Value($2)) }; }), o('FOR Range BY Expression', function() { return { source: LOC(2)(new Value($2)), step: $4 }; }), o('ForStart ForSource', function() { $2.own = $1.own; $2.name = $1[0]; $2.index = $1[1]; return $2; }) ], ForStart: [ o('FOR ForVariables', function() { return $2; }), o('FOR OWN ForVariables', function() { $3.own = true; return $3; }) ], ForValue: [ o('Identifier'), o('ThisProperty'), o('Array', function() { return new Value($1); }), o('Object', function() { return new Value($1); }) ], ForVariables: [ o('ForValue', function() { return [$1]; }), o('ForValue , ForValue', function() { return [$1, $3]; }) ], ForSource: [ o('FORIN Expression', function() { return { source: $2 }; }), o('FOROF Expression', function() { return { source: $2, object: true }; }), o('FORIN Expression WHEN Expression', function() { return { source: $2, guard: $4 }; }), o('FOROF Expression WHEN Expression', function() { return { source: $2, guard: $4, object: true }; }), o('FORIN Expression BY Expression', function() { return { source: $2, step: $4 }; }), o('FORIN Expression WHEN Expression BY Expression', function() { return { source: $2, guard: $4, step: $6 }; }), o('FORIN Expression BY Expression WHEN Expression', function() { return { source: $2, step: $4, guard: $6 }; }) ], Switch: [ o('SWITCH Expression INDENT Whens OUTDENT', function() { return new Switch($2, $4); }), o('SWITCH Expression INDENT Whens ELSE Block OUTDENT', function() { return new Switch($2, $4, $6); }), o('SWITCH INDENT Whens OUTDENT', function() { return new Switch(null, $3); }), o('SWITCH INDENT Whens ELSE Block OUTDENT', function() { return new Switch(null, $3, $5); }) ], Whens: [ o('When'), o('Whens When', function() { return $1.concat($2); }) ], When: [ o('LEADING_WHEN SimpleArgs Block', function() { return [[$2, $3]]; }), o('LEADING_WHEN SimpleArgs Block TERMINATOR', function() { return [[$2, $3]]; }) ], IfBlock: [ o('IF Expression Block', function() { return new If($2, $3, { type: $1 }); }), o('IfBlock ELSE IF Expression Block', function() { return $1.addElse(LOC(3, 5)(new If($4, $5, { type: $3 }))); }) ], If: [ o('IfBlock'), o('IfBlock ELSE Block', function() { return $1.addElse($3); }), o('Statement POST_IF Expression', function() { return new If($3, LOC(1)(Block.wrap([$1])), { type: $2, statement: true }); }), o('Expression POST_IF Expression', function() { return new If($3, LOC(1)(Block.wrap([$1])), { type: $2, statement: true }); }) ], Operation: [ o('UNARY Expression', function() { return new Op($1, $2); }), o('UNARY_MATH Expression', function() { return new Op($1, $2); }), o('- Expression', (function() { return new Op('-', $2); }), { prec: 'UNARY_MATH' }), o('+ Expression', (function() { return new Op('+', $2); }), { prec: 'UNARY_MATH' }), o('YIELD Statement', function() { return new Op($1, $2); }), o('YIELD Expression', function() { return new Op($1, $2); }), o('YIELD FROM Expression', function() { return new Op($1.concat($2), $3); }), o('-- SimpleAssignable', function() { return new Op('--', $2); }), o('++ SimpleAssignable', function() { return new Op('++', $2); }), o('SimpleAssignable --', function() { return new Op('--', $1, null, true); }), o('SimpleAssignable ++', function() { return new Op('++', $1, null, true); }), o('Expression ?', function() { return new Existence($1); }), o('Expression + Expression', function() { return new Op('+', $1, $3); }), o('Expression - Expression', function() { return new Op('-', $1, $3); }), o('Expression MATH Expression', function() { return new Op($2, $1, $3); }), o('Expression ** Expression', function() { return new Op($2, $1, $3); }), o('Expression SHIFT Expression', function() { return new Op($2, $1, $3); }), o('Expression COMPARE Expression', function() { return new Op($2, $1, $3); }), o('Expression LOGIC Expression', function() { return new Op($2, $1, $3); }), o('Expression RELATION Expression', function() { if ($2.charAt(0) === '!') { return new Op($2.slice(1), $1, $3).invert(); } else { return new Op($2, $1, $3); } }), o('SimpleAssignable COMPOUND_ASSIGN Expression', function() { return new Assign($1, $3, $2); }), o('SimpleAssignable COMPOUND_ASSIGN INDENT Expression OUTDENT', function() { return new Assign($1, $4, $2); }), o('SimpleAssignable COMPOUND_ASSIGN TERMINATOR Expression', function() { return new Assign($1, $4, $2); }), o('SimpleAssignable EXTENDS Expression', function() { return new Extends($1, $3); }) ] }; operators = [['left', '.', '?.', '::', '?::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['right', '**'], ['right', 'UNARY_MATH'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', 'YIELD'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['left', 'POST_IF']]; tokens = []; for (name in grammar) { alternatives = grammar[name]; grammar[name] = (function() { var i, j, len, len1, ref, results; results = []; for (i = 0, len = alternatives.length; i < len; i++) { alt = alternatives[i]; ref = alt[0].split(' '); for (j = 0, len1 = ref.length; j < len1; j++) { token = ref[j]; if (!grammar[token]) { tokens.push(token); } } if (name === 'Root') { alt[1] = "return " + alt[1]; } results.push(alt); } return results; })(); } exports.parser = new Parser({ tokens: tokens.join(' '), bnf: grammar, operators: operators.reverse(), startSymbol: 'Root' }); }).call(this); 1.9.3~dfsg/lib/coffee-script/repl.js0000644000000000000000000001462412531364553016103 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, ref, replDefaults, runInContext, updateSyntaxError, vm; fs = require('fs'); path = require('path'); vm = require('vm'); nodeREPL = require('repl'); CoffeeScript = require('./coffee-script'); ref = require('./helpers'), merge = ref.merge, updateSyntaxError = ref.updateSyntaxError; replDefaults = { prompt: 'coffee> ', historyFile: process.env.HOME ? path.join(process.env.HOME, '.coffee_history') : void 0, historyMaxInputSize: 10240, "eval": function(input, context, filename, cb) { var Assign, Block, Literal, Value, ast, err, js, ref1, referencedVars, token, tokens; input = input.replace(/\uFF00/g, '\n'); input = input.replace(/^\(([\s\S]*)\n\)$/m, '$1'); ref1 = require('./nodes'), Block = ref1.Block, Assign = ref1.Assign, Value = ref1.Value, Literal = ref1.Literal; try { tokens = CoffeeScript.tokens(input); referencedVars = (function() { var i, len, results; results = []; for (i = 0, len = tokens.length; i < len; i++) { token = tokens[i]; if (token.variable) { results.push(token[1]); } } return results; })(); ast = CoffeeScript.nodes(tokens); ast = new Block([new Assign(new Value(new Literal('_')), ast, '=')]); js = ast.compile({ bare: true, locals: Object.keys(context), referencedVars: referencedVars }); return cb(null, runInContext(js, context, filename)); } catch (_error) { err = _error; updateSyntaxError(err, input); return cb(err); } } }; runInContext = function(js, context, filename) { if (context === global) { return vm.runInThisContext(js, filename); } else { return vm.runInContext(js, context, filename); } }; addMultilineHandler = function(repl) { var inputStream, multiline, nodeLineListener, origPrompt, outputStream, ref1, rli; rli = repl.rli, inputStream = repl.inputStream, outputStream = repl.outputStream; origPrompt = (ref1 = repl._prompt) != null ? ref1 : repl.prompt; multiline = { enabled: false, initialPrompt: origPrompt.replace(/^[^> ]*/, function(x) { return x.replace(/./g, '-'); }), prompt: origPrompt.replace(/^[^> ]*>?/, function(x) { return x.replace(/./g, '.'); }), buffer: '' }; nodeLineListener = rli.listeners('line')[0]; rli.removeListener('line', nodeLineListener); rli.on('line', function(cmd) { if (multiline.enabled) { multiline.buffer += cmd + "\n"; rli.setPrompt(multiline.prompt); rli.prompt(true); } else { rli.setPrompt(origPrompt); nodeLineListener(cmd); } }); return inputStream.on('keypress', function(char, key) { if (!(key && key.ctrl && !key.meta && !key.shift && key.name === 'v')) { return; } if (multiline.enabled) { if (!multiline.buffer.match(/\n/)) { multiline.enabled = !multiline.enabled; rli.setPrompt(origPrompt); rli.prompt(true); return; } if ((rli.line != null) && !rli.line.match(/^\s*$/)) { return; } multiline.enabled = !multiline.enabled; rli.line = ''; rli.cursor = 0; rli.output.cursorTo(0); rli.output.clearLine(1); multiline.buffer = multiline.buffer.replace(/\n/g, '\uFF00'); rli.emit('line', multiline.buffer); multiline.buffer = ''; } else { multiline.enabled = !multiline.enabled; rli.setPrompt(multiline.initialPrompt); rli.prompt(true); } }); }; addHistory = function(repl, filename, maxSize) { var buffer, fd, lastLine, readFd, size, stat; lastLine = null; try { stat = fs.statSync(filename); size = Math.min(maxSize, stat.size); readFd = fs.openSync(filename, 'r'); buffer = new Buffer(size); fs.readSync(readFd, buffer, 0, size, stat.size - size); fs.close(readFd); repl.rli.history = buffer.toString().split('\n').reverse(); if (stat.size > maxSize) { repl.rli.history.pop(); } if (repl.rli.history[0] === '') { repl.rli.history.shift(); } repl.rli.historyIndex = -1; lastLine = repl.rli.history[0]; } catch (_error) {} fd = fs.openSync(filename, 'a'); repl.rli.addListener('line', function(code) { if (code && code.length && code !== '.history' && lastLine !== code) { fs.write(fd, code + "\n"); return lastLine = code; } }); repl.on('exit', function() { return fs.close(fd); }); return repl.commands[getCommandId(repl, 'history')] = { help: 'Show command history', action: function() { repl.outputStream.write((repl.rli.history.slice(0).reverse().join('\n')) + "\n"); return repl.displayPrompt(); } }; }; getCommandId = function(repl, commandName) { var commandsHaveLeadingDot; commandsHaveLeadingDot = repl.commands['.help'] != null; if (commandsHaveLeadingDot) { return "." + commandName; } else { return commandName; } }; module.exports = { start: function(opts) { var build, major, minor, ref1, repl; if (opts == null) { opts = {}; } ref1 = process.versions.node.split('.').map(function(n) { return parseInt(n); }), major = ref1[0], minor = ref1[1], build = ref1[2]; if (major === 0 && minor < 8) { console.warn("Node 0.8.0+ required for CoffeeScript REPL"); process.exit(1); } CoffeeScript.register(); process.argv = ['coffee'].concat(process.argv.slice(2)); opts = merge(replDefaults, opts); repl = nodeREPL.start(opts); if (opts.prelude) { runInContext(opts.prelude, repl.context, 'prelude'); } repl.on('exit', function() { if (!repl.rli.closed) { return repl.outputStream.write('\n'); } }); addMultilineHandler(repl); if (opts.historyFile) { addHistory(repl, opts.historyFile, opts.historyMaxInputSize); } repl.commands[getCommandId(repl, 'load')].help = 'Load code from a file into this REPL session'; return repl; } }; }).call(this); 1.9.3~dfsg/lib/coffee-script/coffee-script.js0000644000000000000000000002740412531364553017672 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var Lexer, SourceMap, base, compile, ext, formatSourcePosition, fs, getSourceMap, helpers, i, len, lexer, parser, path, ref, sourceMaps, vm, withPrettyErrors, hasProp = {}.hasOwnProperty, 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; }; fs = require('fs'); vm = require('vm'); path = require('path'); Lexer = require('./lexer').Lexer; parser = require('./parser').parser; helpers = require('./helpers'); SourceMap = require('./sourcemap'); exports.VERSION = '1.9.3'; exports.FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.md']; exports.helpers = helpers; withPrettyErrors = function(fn) { return function(code, options) { var err; if (options == null) { options = {}; } try { return fn.call(this, code, options); } catch (_error) { err = _error; if (typeof code !== 'string') { throw err; } throw helpers.updateSyntaxError(err, code, options.filename); } }; }; exports.compile = compile = withPrettyErrors(function(code, options) { var answer, currentColumn, currentLine, extend, fragment, fragments, header, i, js, len, map, merge, newLines, token, tokens; merge = helpers.merge, extend = helpers.extend; options = extend({}, options); if (options.sourceMap) { map = new SourceMap; } tokens = lexer.tokenize(code, options); options.referencedVars = (function() { var i, len, results; results = []; for (i = 0, len = tokens.length; i < len; i++) { token = tokens[i]; if (token.variable) { results.push(token[1]); } } return results; })(); fragments = parser.parse(tokens).compileToFragments(options); currentLine = 0; if (options.header) { currentLine += 1; } if (options.shiftLine) { currentLine += 1; } currentColumn = 0; js = ""; for (i = 0, len = fragments.length; i < len; i++) { fragment = fragments[i]; if (options.sourceMap) { if (fragment.locationData && !/^[;\s]*$/.test(fragment.code)) { map.add([fragment.locationData.first_line, fragment.locationData.first_column], [currentLine, currentColumn], { noReplace: true }); } newLines = helpers.count(fragment.code, "\n"); currentLine += newLines; if (newLines) { currentColumn = fragment.code.length - (fragment.code.lastIndexOf("\n") + 1); } else { currentColumn += fragment.code.length; } } js += fragment.code; } if (options.header) { header = "Generated by CoffeeScript " + this.VERSION; js = "// " + header + "\n" + js; } if (options.sourceMap) { answer = { js: js }; answer.sourceMap = map; answer.v3SourceMap = map.generate(options, code); return answer; } else { return js; } }); exports.tokens = withPrettyErrors(function(code, options) { return lexer.tokenize(code, options); }); exports.nodes = withPrettyErrors(function(source, options) { if (typeof source === 'string') { return parser.parse(lexer.tokenize(source, options)); } else { return parser.parse(source); } }); exports.run = function(code, options) { var answer, dir, mainModule, ref; if (options == null) { options = {}; } mainModule = require.main; mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.'; mainModule.moduleCache && (mainModule.moduleCache = {}); dir = options.filename ? path.dirname(fs.realpathSync(options.filename)) : fs.realpathSync('.'); mainModule.paths = require('module')._nodeModulePaths(dir); if (!helpers.isCoffee(mainModule.filename) || require.extensions) { answer = compile(code, options); code = (ref = answer.js) != null ? ref : answer; } return mainModule._compile(code, mainModule.filename); }; exports["eval"] = function(code, options) { var Module, _module, _require, createContext, i, isContext, js, k, len, o, r, ref, ref1, ref2, ref3, sandbox, v; if (options == null) { options = {}; } if (!(code = code.trim())) { return; } createContext = (ref = vm.Script.createContext) != null ? ref : vm.createContext; isContext = (ref1 = vm.isContext) != null ? ref1 : function(ctx) { return options.sandbox instanceof createContext().constructor; }; if (createContext) { if (options.sandbox != null) { if (isContext(options.sandbox)) { sandbox = options.sandbox; } else { sandbox = createContext(); ref2 = options.sandbox; for (k in ref2) { if (!hasProp.call(ref2, k)) continue; v = ref2[k]; sandbox[k] = v; } } sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox; } else { sandbox = global; } sandbox.__filename = options.filename || 'eval'; sandbox.__dirname = path.dirname(sandbox.__filename); if (!(sandbox !== global || sandbox.module || sandbox.require)) { Module = require('module'); sandbox.module = _module = new Module(options.modulename || 'eval'); sandbox.require = _require = function(path) { return Module._load(path, _module, true); }; _module.filename = sandbox.__filename; ref3 = Object.getOwnPropertyNames(require); for (i = 0, len = ref3.length; i < len; i++) { r = ref3[i]; if (r !== 'paths') { _require[r] = require[r]; } } _require.paths = _module.paths = Module._nodeModulePaths(process.cwd()); _require.resolve = function(request) { return Module._resolveFilename(request, _module); }; } } o = {}; for (k in options) { if (!hasProp.call(options, k)) continue; v = options[k]; o[k] = v; } o.bare = true; js = compile(code, o); if (sandbox === global) { return vm.runInThisContext(js); } else { return vm.runInContext(js, sandbox); } }; exports.register = function() { return require('./register'); }; if (require.extensions) { ref = this.FILE_EXTENSIONS; for (i = 0, len = ref.length; i < len; i++) { ext = ref[i]; if ((base = require.extensions)[ext] == null) { base[ext] = function() { throw new Error("Use CoffeeScript.register() or require the coffee-script/register module to require " + ext + " files."); }; } } } exports._compileFile = function(filename, sourceMap) { var answer, err, raw, stripped; if (sourceMap == null) { sourceMap = false; } raw = fs.readFileSync(filename, 'utf8'); stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw; try { answer = compile(stripped, { filename: filename, sourceMap: sourceMap, literate: helpers.isLiterate(filename) }); } catch (_error) { err = _error; throw helpers.updateSyntaxError(err, stripped, filename); } return answer; }; lexer = new Lexer; parser.lexer = { lex: function() { var tag, token; token = parser.tokens[this.pos++]; if (token) { tag = token[0], this.yytext = token[1], this.yylloc = token[2]; parser.errorToken = token.origin || token; this.yylineno = this.yylloc.first_line; } else { tag = ''; } return tag; }, setInput: function(tokens) { parser.tokens = tokens; return this.pos = 0; }, upcomingInput: function() { return ""; } }; parser.yy = require('./nodes'); parser.yy.parseError = function(message, arg) { var errorLoc, errorTag, errorText, errorToken, token, tokens; token = arg.token; errorToken = parser.errorToken, tokens = parser.tokens; errorTag = errorToken[0], errorText = errorToken[1], errorLoc = errorToken[2]; errorText = (function() { switch (false) { case errorToken !== tokens[tokens.length - 1]: return 'end of input'; case errorTag !== 'INDENT' && errorTag !== 'OUTDENT': return 'indentation'; case errorTag !== 'IDENTIFIER' && errorTag !== 'NUMBER' && errorTag !== 'STRING' && errorTag !== 'STRING_START' && errorTag !== 'REGEX' && errorTag !== 'REGEX_START': return errorTag.replace(/_START$/, '').toLowerCase(); default: return helpers.nameWhitespaceCharacter(errorText); } })(); return helpers.throwSyntaxError("unexpected " + errorText, errorLoc); }; formatSourcePosition = function(frame, getSourceMapping) { var as, column, fileLocation, fileName, functionName, isConstructor, isMethodCall, line, methodName, source, tp, typeName; fileName = void 0; fileLocation = ''; if (frame.isNative()) { fileLocation = "native"; } else { if (frame.isEval()) { fileName = frame.getScriptNameOrSourceURL(); if (!fileName) { fileLocation = (frame.getEvalOrigin()) + ", "; } } else { fileName = frame.getFileName(); } fileName || (fileName = ""); line = frame.getLineNumber(); column = frame.getColumnNumber(); source = getSourceMapping(fileName, line, column); fileLocation = source ? fileName + ":" + source[0] + ":" + source[1] : fileName + ":" + line + ":" + column; } functionName = frame.getFunctionName(); isConstructor = frame.isConstructor(); isMethodCall = !(frame.isToplevel() || isConstructor); if (isMethodCall) { methodName = frame.getMethodName(); typeName = frame.getTypeName(); if (functionName) { tp = as = ''; if (typeName && functionName.indexOf(typeName)) { tp = typeName + "."; } if (methodName && functionName.indexOf("." + methodName) !== functionName.length - methodName.length - 1) { as = " [as " + methodName + "]"; } return "" + tp + functionName + as + " (" + fileLocation + ")"; } else { return typeName + "." + (methodName || '') + " (" + fileLocation + ")"; } } else if (isConstructor) { return "new " + (functionName || '') + " (" + fileLocation + ")"; } else if (functionName) { return functionName + " (" + fileLocation + ")"; } else { return fileLocation; } }; sourceMaps = {}; getSourceMap = function(filename) { var answer, ref1; if (sourceMaps[filename]) { return sourceMaps[filename]; } if (ref1 = path != null ? path.extname(filename) : void 0, indexOf.call(exports.FILE_EXTENSIONS, ref1) < 0) { return; } answer = exports._compileFile(filename, true); return sourceMaps[filename] = answer.sourceMap; }; Error.prepareStackTrace = function(err, stack) { var frame, frames, getSourceMapping; getSourceMapping = function(filename, line, column) { var answer, sourceMap; sourceMap = getSourceMap(filename); if (sourceMap) { answer = sourceMap.sourceLocation([line - 1, column - 1]); } if (answer) { return [answer[0] + 1, answer[1] + 1]; } else { return null; } }; frames = (function() { var j, len1, results; results = []; for (j = 0, len1 = stack.length; j < len1; j++) { frame = stack[j]; if (frame.getFunction() === exports.run) { break; } results.push(" at " + (formatSourcePosition(frame, getSourceMapping))); } return results; })(); return (err.toString()) + "\n" + (frames.join('\n')) + "\n"; }; }).call(this); 1.9.3~dfsg/lib/coffee-script/rewriter.js0000644000000000000000000004451212531364553017003 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var BALANCED_PAIRS, CALL_CLOSERS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, ref, rite, 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; }, slice = [].slice; generate = function(tag, value, origin) { var tok; tok = [tag, value]; tok.generated = true; if (origin) { tok.origin = origin; } return tok; }; 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(); 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); } 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); } 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() { var fuzz, i, j, k, pattern, ref, ref1; i = arguments[0], pattern = 2 <= arguments.length ? slice.call(arguments, 1) : []; 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) { 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; }; 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)); } 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; }; 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 } ]); 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) { var idx, val; if (startsLine == null) { startsLine = true; } 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()) { stack.pop(); } 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 { stack.pop(); } } 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'; } 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; } }).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); } } 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); } } 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.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.apply(tokens, [i, 1].concat(slice.call(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.apply(tokens, [i + j, 0].concat(slice.call(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; }); }; 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]; }; Rewriter.prototype.generate = generate; Rewriter.prototype.tag = function(i) { var ref; return (ref = this.tokens[i]) != null ? ref[0] : void 0; }; return Rewriter; })(); BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END'], ['STRING_START', 'STRING_END'], ['REGEX_START', 'REGEX_END']]; exports.INVERSES = INVERSES = {}; EXPRESSION_START = []; EXPRESSION_END = []; for (k = 0, len = BALANCED_PAIRS.length; k < len; k++) { ref = BALANCED_PAIRS[k], left = ref[0], rite = ref[1]; EXPRESSION_START.push(INVERSES[rite] = left); EXPRESSION_END.push(INVERSES[left] = rite); } EXPRESSION_CLOSE = ['CATCH', 'THEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END); IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS']; IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'STRING_START', 'JS', 'REGEX', 'REGEX_START', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL', 'UNDEFINED', 'UNARY', 'YIELD', 'UNARY_MATH', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++']; IMPLICIT_UNSPACED_CALL = ['+', '-']; IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR']; SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN']; SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN']; LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT']; CALL_CLOSERS = ['.', '?.', '::', '?::']; }).call(this); 1.9.3~dfsg/lib/coffee-script/index.js0000644000000000000000000000030012531364553016232 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var key, ref, val; ref = require('./coffee-script'); for (key in ref) { val = ref[key]; exports[key] = val; } }).call(this); 1.9.3~dfsg/lib/coffee-script/helpers.js0000644000000000000000000001533512531364553016603 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var buildLocationData, extend, flatten, ref, repeat, syntaxErrorToString; exports.starts = function(string, literal, start) { return literal === string.substr(start, literal.length); }; exports.ends = function(string, literal, back) { var len; len = literal.length; return literal === string.substr(string.length - len - (back || 0), len); }; exports.repeat = repeat = function(str, n) { var res; res = ''; while (n > 0) { if (n & 1) { res += str; } n >>>= 1; str += str; } return res; }; exports.compact = function(array) { var i, item, len1, results; results = []; for (i = 0, len1 = array.length; i < len1; i++) { item = array[i]; if (item) { results.push(item); } } return results; }; exports.count = function(string, substr) { var num, pos; num = pos = 0; if (!substr.length) { return 1 / 0; } while (pos = 1 + string.indexOf(substr, pos)) { num++; } return num; }; exports.merge = function(options, overrides) { return extend(extend({}, options), overrides); }; extend = exports.extend = function(object, properties) { var key, val; for (key in properties) { val = properties[key]; object[key] = val; } return object; }; exports.flatten = flatten = function(array) { var element, flattened, i, len1; flattened = []; for (i = 0, len1 = array.length; i < len1; i++) { element = array[i]; if (element instanceof Array) { flattened = flattened.concat(flatten(element)); } else { flattened.push(element); } } return flattened; }; exports.del = function(obj, key) { var val; val = obj[key]; delete obj[key]; return val; }; exports.some = (ref = Array.prototype.some) != null ? ref : function(fn) { var e, i, len1; for (i = 0, len1 = this.length; i < len1; i++) { e = this[i]; if (fn(e)) { return true; } } return false; }; exports.invertLiterate = function(code) { var line, lines, maybe_code; maybe_code = true; lines = (function() { var i, len1, ref1, results; ref1 = code.split('\n'); results = []; for (i = 0, len1 = ref1.length; i < len1; i++) { line = ref1[i]; if (maybe_code && /^([ ]{4}|[ ]{0,3}\t)/.test(line)) { results.push(line); } else if (maybe_code = /^\s*$/.test(line)) { results.push(line); } else { results.push('# ' + line); } } return results; })(); return lines.join('\n'); }; buildLocationData = function(first, last) { if (!last) { return first; } else { return { first_line: first.first_line, first_column: first.first_column, last_line: last.last_line, last_column: last.last_column }; } }; exports.addLocationDataFn = function(first, last) { return function(obj) { if (((typeof obj) === 'object') && (!!obj['updateLocationDataIfMissing'])) { obj.updateLocationDataIfMissing(buildLocationData(first, last)); } return obj; }; }; exports.locationDataToString = function(obj) { var locationData; if (("2" in obj) && ("first_line" in obj[2])) { locationData = obj[2]; } else if ("first_line" in obj) { locationData = obj; } if (locationData) { return ((locationData.first_line + 1) + ":" + (locationData.first_column + 1) + "-") + ((locationData.last_line + 1) + ":" + (locationData.last_column + 1)); } else { return "No location data"; } }; exports.baseFileName = function(file, stripExt, useWinPathSep) { var parts, pathSep; if (stripExt == null) { stripExt = false; } if (useWinPathSep == null) { useWinPathSep = false; } pathSep = useWinPathSep ? /\\|\// : /\//; parts = file.split(pathSep); file = parts[parts.length - 1]; if (!(stripExt && file.indexOf('.') >= 0)) { return file; } parts = file.split('.'); parts.pop(); if (parts[parts.length - 1] === 'coffee' && parts.length > 1) { parts.pop(); } return parts.join('.'); }; exports.isCoffee = function(file) { return /\.((lit)?coffee|coffee\.md)$/.test(file); }; exports.isLiterate = function(file) { return /\.(litcoffee|coffee\.md)$/.test(file); }; exports.throwSyntaxError = function(message, location) { var error; error = new SyntaxError(message); error.location = location; error.toString = syntaxErrorToString; error.stack = error.toString(); throw error; }; exports.updateSyntaxError = function(error, code, filename) { if (error.toString === syntaxErrorToString) { error.code || (error.code = code); error.filename || (error.filename = filename); error.stack = error.toString(); } return error; }; syntaxErrorToString = function() { var codeLine, colorize, colorsEnabled, end, filename, first_column, first_line, last_column, last_line, marker, ref1, ref2, ref3, ref4, start; if (!(this.code && this.location)) { return Error.prototype.toString.call(this); } ref1 = this.location, first_line = ref1.first_line, first_column = ref1.first_column, last_line = ref1.last_line, last_column = ref1.last_column; if (last_line == null) { last_line = first_line; } if (last_column == null) { last_column = first_column; } filename = this.filename || '[stdin]'; codeLine = this.code.split('\n')[first_line]; start = first_column; end = first_line === last_line ? last_column + 1 : codeLine.length; marker = codeLine.slice(0, start).replace(/[^\s]/g, ' ') + repeat('^', end - start); if (typeof process !== "undefined" && process !== null) { colorsEnabled = ((ref2 = process.stdout) != null ? ref2.isTTY : void 0) && !((ref3 = process.env) != null ? ref3.NODE_DISABLE_COLORS : void 0); } if ((ref4 = this.colorful) != null ? ref4 : colorsEnabled) { colorize = function(str) { return "\x1B[1;31m" + str + "\x1B[0m"; }; codeLine = codeLine.slice(0, start) + colorize(codeLine.slice(start, end)) + codeLine.slice(end); marker = colorize(marker); } return filename + ":" + (first_line + 1) + ":" + (first_column + 1) + ": error: " + this.message + "\n" + codeLine + "\n" + marker; }; exports.nameWhitespaceCharacter = function(string) { switch (string) { case ' ': return 'space'; case '\n': return 'newline'; case '\r': return 'carriage return'; case '\t': return 'tab'; default: return string; } }; }).call(this); 1.9.3~dfsg/lib/coffee-script/sourcemap.js0000644000000000000000000001110212531364553017123 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var LineMap, SourceMap; LineMap = (function() { function LineMap(line1) { this.line = line1; this.columns = []; } LineMap.prototype.add = function(column, arg, options) { var sourceColumn, sourceLine; sourceLine = arg[0], sourceColumn = arg[1]; if (options == null) { options = {}; } if (this.columns[column] && options.noReplace) { return; } return this.columns[column] = { line: this.line, column: column, sourceLine: sourceLine, sourceColumn: sourceColumn }; }; LineMap.prototype.sourceLocation = function(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; if (options == null) { options = {}; } 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--; } return lineMap && lineMap.sourceLocation(column); }; SourceMap.prototype.generate = function(options, code) { var buffer, i, j, lastColumn, lastSourceColumn, lastSourceLine, len, len1, lineMap, lineNumber, mapping, needComma, ref, ref1, v3, writingline; if (options == null) { options = {}; } if (code == null) { code = null; } 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; } } } v3 = { version: 3, file: options.generatedFile || '', sourceRoot: options.sourceRoot || '', sources: options.sourceFiles || [''], names: [], mappings: buffer }; if (options.inline) { v3.sourcesContent = [code]; } return JSON.stringify(v3, null, 2); }; VLQ_SHIFT = 5; VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT; 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; })(); module.exports = SourceMap; }).call(this); 1.9.3~dfsg/lib/coffee-script/optparse.js0000644000000000000000000000775012531364553017000 0ustar rootroot// Generated by CoffeeScript 1.9.3 (function() { var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat; repeat = require('./helpers').repeat; exports.OptionParser = OptionParser = (function() { function OptionParser(rules, banner) { this.banner = banner; this.rules = buildRules(rules); } OptionParser.prototype.parse = function(args) { var arg, i, isOption, j, k, len, len1, matchedRule, options, originalArgs, pos, ref, rule, seenNonOptionArg, skippingArgument, value; options = { "arguments": [] }; skippingArgument = false; originalArgs = args; args = normalizeArguments(args); for (i = j = 0, len = args.length; j < len; i = ++j) { arg = args[i]; if (skippingArgument) { skippingArgument = false; continue; } if (arg === '--') { pos = originalArgs.indexOf('--'); options["arguments"] = options["arguments"].concat(originalArgs.slice(pos + 1)); break; } isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG)); seenNonOptionArg = options["arguments"].length > 0; if (!seenNonOptionArg) { matchedRule = false; ref = this.rules; for (k = 0, len1 = ref.length; k < len1; k++) { rule = ref[k]; if (rule.shortFlag === arg || rule.longFlag === arg) { value = true; if (rule.hasArgument) { skippingArgument = true; value = args[i + 1]; } options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value; matchedRule = true; break; } } if (isOption && !matchedRule) { throw new Error("unrecognized option: " + arg); } } if (seenNonOptionArg || !isOption) { options["arguments"].push(arg); } } return options; }; OptionParser.prototype.help = function() { var j, len, letPart, lines, ref, rule, spaces; lines = []; if (this.banner) { lines.unshift(this.banner + "\n"); } ref = this.rules; for (j = 0, len = ref.length; j < len; j++) { rule = ref[j]; spaces = 15 - rule.longFlag.length; spaces = spaces > 0 ? repeat(' ', spaces) : ''; letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' '; lines.push(' ' + letPart + rule.longFlag + spaces + rule.description); } return "\n" + (lines.join('\n')) + "\n"; }; return OptionParser; })(); LONG_FLAG = /^(--\w[\w\-]*)/; SHORT_FLAG = /^(-\w)$/; MULTI_FLAG = /^-(\w{2,})/; OPTIONAL = /\[(\w+(\*?))\]/; buildRules = function(rules) { var j, len, results, tuple; results = []; for (j = 0, len = rules.length; j < len; j++) { tuple = rules[j]; if (tuple.length < 3) { tuple.unshift(null); } results.push(buildRule.apply(null, tuple)); } return results; }; buildRule = function(shortFlag, longFlag, description, options) { var match; if (options == null) { options = {}; } match = longFlag.match(OPTIONAL); longFlag = longFlag.match(LONG_FLAG)[1]; return { name: longFlag.substr(2), shortFlag: shortFlag, longFlag: longFlag, description: description, hasArgument: !!(match && match[1]), isList: !!(match && match[2]) }; }; normalizeArguments = function(args) { var arg, j, k, l, len, len1, match, ref, result; args = args.slice(0); result = []; for (j = 0, len = args.length; j < len; j++) { arg = args[j]; if (match = arg.match(MULTI_FLAG)) { ref = match[1].split(''); for (k = 0, len1 = ref.length; k < len1; k++) { l = ref[k]; result.push('-' + l); } } else { result.push(arg); } } return result; }; }).call(this); 1.9.3~dfsg/package.json0000644000000000000000000000166512531364553013573 0ustar rootroot{ "name": "coffee-script", "description": "Unfancy JavaScript", "keywords": [ "javascript", "language", "coffeescript", "compiler" ], "author": "Jeremy Ashkenas", "version": "1.9.3", "license": "MIT", "engines": { "node": ">=0.8.0" }, "directories": { "lib": "./lib/coffee-script" }, "main": "./lib/coffee-script/coffee-script", "bin": { "coffee": "./bin/coffee", "cake": "./bin/cake" }, "preferGlobal": true, "scripts": { "test": "node ./bin/cake test", "test-harmony": "node --harmony ./bin/cake test" }, "homepage": "http://coffeescript.org", "bugs": "https://github.com/jashkenas/coffeescript/issues", "repository": { "type": "git", "url": "git://github.com/jashkenas/coffeescript.git" }, "devDependencies": { "uglify-js": "~2.2", "jison": ">=0.2.0", "highlight.js": "~8.0.0", "underscore": "~1.5.2", "docco": "~0.7.0" } } 1.9.3~dfsg/src/0000755000000000000000000000000012531364553012064 5ustar rootroot1.9.3~dfsg/src/lexer.coffee0000644000000000000000000010167212531364553014363 0ustar rootroot# The CoffeeScript Lexer. Uses a series of token-matching regexes to attempt # matches against the beginning of the source code. When a match is found, # a token is produced, we consume the match, and start again. Tokens are in the # form: # # [tag, value, locationData] # # where locationData is {first_line, first_column, last_line, last_column}, which is a # format that can be fed directly into [Jison](http://github.com/zaach/jison). These # are read by jison in the `parser.lexer` function defined in coffee-script.coffee. {Rewriter, INVERSES} = require './rewriter' # Import the helpers we need. {count, starts, compact, repeat, invertLiterate, locationDataToString, throwSyntaxError} = require './helpers' # The Lexer Class # --------------- # The Lexer class reads a stream of CoffeeScript and divvies it up into tagged # tokens. Some potential ambiguity in the grammar has been avoided by # pushing some extra smarts into the Lexer. exports.Lexer = class Lexer # **tokenize** is the Lexer's main method. Scan by attempting to match tokens # one at a time, using a regular expression anchored at the start of the # remaining code, or a custom recursive token-matching method # (for interpolations). When the next token has been recorded, we move forward # within the code past the token, and begin again. # # Each tokenizing method is responsible for returning the number of characters # it has consumed. # # Before returning the token stream, run it through the [Rewriter](rewriter.html). tokenize: (code, opts = {}) -> @literate = opts.literate # Are we lexing literate CoffeeScript? @indent = 0 # The current indentation level. @baseIndent = 0 # The overall minimum indentation level @indebt = 0 # The over-indentation at the current level. @outdebt = 0 # The under-outdentation at the current level. @indents = [] # The stack of all current indentation levels. @ends = [] # The stack for pairing up tokens. @tokens = [] # Stream of parsed tokens in the form `['TYPE', value, location data]`. @chunkLine = opts.line or 0 # The start line for the current @chunk. @chunkColumn = opts.column or 0 # The start column of the current @chunk. code = @clean code # The stripped, cleaned original source code. # At every position, run through this list of attempted matches, # short-circuiting if any of them succeed. Their order determines precedence: # `@literalToken` is the fallback catch-all. i = 0 while @chunk = code[i..] consumed = \ @identifierToken() or @commentToken() or @whitespaceToken() or @lineToken() or @stringToken() or @numberToken() or @regexToken() or @jsToken() or @literalToken() # Update position [@chunkLine, @chunkColumn] = @getLineAndColumnFromChunk consumed i += consumed return {@tokens, index: i} if opts.untilBalanced and @ends.length is 0 @closeIndentation() @error "missing #{end.tag}", end.origin[2] if end = @ends.pop() return @tokens if opts.rewrite is off (new Rewriter).rewrite @tokens # Preprocess the code to remove leading and trailing whitespace, carriage # returns, etc. If we're lexing literate CoffeeScript, strip external Markdown # by removing all lines that aren't indented by at least four spaces or a tab. clean: (code) -> code = code.slice(1) if code.charCodeAt(0) is BOM code = code.replace(/\r/g, '').replace TRAILING_SPACES, '' if WHITESPACE.test code code = "\n#{code}" @chunkLine-- code = invertLiterate code if @literate code # Tokenizers # ---------- # Matches identifying literals: variables, keywords, method names, etc. # Check to ensure that JavaScript reserved words aren't being used as # identifiers. Because CoffeeScript reserves a handful of keywords that are # allowed in JavaScript, we're careful not to tag them as keywords when # referenced as property names here, so you can still do `jQuery.is()` even # though `is` means `===` otherwise. identifierToken: -> return 0 unless match = IDENTIFIER.exec @chunk [input, id, colon] = match # Preserve length of id for location data idLength = id.length poppedToken = undefined if id is 'own' and @tag() is 'FOR' @token 'OWN', id return id.length if id is 'from' and @tag() is 'YIELD' @token 'FROM', id return id.length [..., prev] = @tokens forcedIdentifier = colon or prev? and (prev[0] in ['.', '?.', '::', '?::'] or not prev.spaced and prev[0] is '@') tag = 'IDENTIFIER' if not forcedIdentifier and (id in JS_KEYWORDS or id in COFFEE_KEYWORDS) tag = id.toUpperCase() if tag is 'WHEN' and @tag() in LINE_BREAK tag = 'LEADING_WHEN' else if tag is 'FOR' @seenFor = yes else if tag is 'UNLESS' tag = 'IF' else if tag in UNARY tag = 'UNARY' else if tag in RELATION if tag isnt 'INSTANCEOF' and @seenFor tag = 'FOR' + tag @seenFor = no else tag = 'RELATION' if @value() is '!' poppedToken = @tokens.pop() id = '!' + id if id in JS_FORBIDDEN if forcedIdentifier tag = 'IDENTIFIER' id = new String id id.reserved = yes else if id in RESERVED @error "reserved word '#{id}'", length: id.length unless forcedIdentifier if id in COFFEE_ALIASES alias = id id = COFFEE_ALIAS_MAP[id] tag = switch id when '!' then 'UNARY' when '==', '!=' then 'COMPARE' when '&&', '||' then 'LOGIC' when 'true', 'false' then 'BOOL' when 'break', 'continue' then 'STATEMENT' else tag tagToken = @token tag, id, 0, idLength tagToken.origin = [tag, alias, tagToken[2]] if alias tagToken.variable = not forcedIdentifier if poppedToken [tagToken[2].first_line, tagToken[2].first_column] = [poppedToken[2].first_line, poppedToken[2].first_column] if colon colonOffset = input.lastIndexOf ':' @token ':', ':', colonOffset, colon.length input.length # Matches numbers, including decimals, hex, and exponential notation. # Be careful not to interfere with ranges-in-progress. numberToken: -> return 0 unless match = NUMBER.exec @chunk number = match[0] lexedLength = number.length if /^0[BOX]/.test number @error "radix prefix in '#{number}' must be lowercase", offset: 1 else if /E/.test(number) and not /^0x/.test number @error "exponential notation in '#{number}' must be indicated with a lowercase 'e'", offset: number.indexOf('E') else if /^0\d*[89]/.test number @error "decimal literal '#{number}' must not be prefixed with '0'", length: lexedLength else if /^0\d+/.test number @error "octal literal '#{number}' must be prefixed with '0o'", length: lexedLength if octalLiteral = /^0o([0-7]+)/.exec number number = '0x' + parseInt(octalLiteral[1], 8).toString 16 if binaryLiteral = /^0b([01]+)/.exec number number = '0x' + parseInt(binaryLiteral[1], 2).toString 16 @token 'NUMBER', number, 0, lexedLength lexedLength # Matches strings, including multi-line strings, as well as heredocs, with or without # interpolation. stringToken: -> [quote] = STRING_START.exec(@chunk) || [] return 0 unless quote regex = switch quote when "'" then STRING_SINGLE when '"' then STRING_DOUBLE when "'''" then HEREDOC_SINGLE when '"""' then HEREDOC_DOUBLE heredoc = quote.length is 3 {tokens, index: end} = @matchWithInterpolations regex, quote $ = tokens.length - 1 delimiter = quote.charAt(0) if heredoc # Find the smallest indentation. It will be removed from all lines later. indent = null doc = (token[1] for token, i in tokens when token[0] is 'NEOSTRING').join '#{}' while match = HEREDOC_INDENT.exec doc attempt = match[1] indent = attempt if indent is null or 0 < attempt.length < indent.length indentRegex = /// ^#{indent} ///gm if indent @mergeInterpolationTokens tokens, {delimiter}, (value, i) => value = @formatString value value = value.replace LEADING_BLANK_LINE, '' if i is 0 value = value.replace TRAILING_BLANK_LINE, '' if i is $ value = value.replace indentRegex, '' if indentRegex value else @mergeInterpolationTokens tokens, {delimiter}, (value, i) => value = @formatString value value = value.replace SIMPLE_STRING_OMIT, (match, offset) -> if (i is 0 and offset is 0) or (i is $ and offset + match.length is value.length) '' else ' ' value end # Matches and consumes comments. commentToken: -> return 0 unless match = @chunk.match COMMENT [comment, here] = match if here if match = HERECOMMENT_ILLEGAL.exec comment @error "block comments cannot contain #{match[0]}", offset: match.index, length: match[0].length if here.indexOf('\n') >= 0 here = here.replace /// \n #{repeat ' ', @indent} ///g, '\n' @token 'HERECOMMENT', here, 0, comment.length comment.length # Matches JavaScript interpolated directly into the source via backticks. jsToken: -> return 0 unless @chunk.charAt(0) is '`' and match = JSTOKEN.exec @chunk @token 'JS', (script = match[0])[1...-1], 0, script.length script.length # Matches regular expression literals, as well as multiline extended ones. # Lexing regular expressions is difficult to distinguish from division, so we # borrow some basic heuristics from JavaScript and Ruby. regexToken: -> switch when match = REGEX_ILLEGAL.exec @chunk @error "regular expressions cannot begin with #{match[2]}", offset: match.index + match[1].length when match = @matchWithInterpolations HEREGEX, '///' {tokens, index} = match when match = REGEX.exec @chunk [regex, body, closed] = match @validateEscapes body, isRegex: yes, offsetInChunk: 1 index = regex.length [..., prev] = @tokens if prev if prev.spaced and prev[0] in CALLABLE return 0 if not closed or POSSIBLY_DIVISION.test regex else if prev[0] in NOT_REGEX return 0 @error 'missing / (unclosed regex)' unless closed else return 0 [flags] = REGEX_FLAGS.exec @chunk[index..] end = index + flags.length origin = @makeToken 'REGEX', null, 0, end switch when not VALID_FLAGS.test flags @error "invalid regular expression flags #{flags}", offset: index, length: flags.length when regex or tokens.length is 1 body ?= @formatHeregex tokens[0][1] @token 'REGEX', "#{@makeDelimitedLiteral body, delimiter: '/'}#{flags}", 0, end, origin else @token 'REGEX_START', '(', 0, 0, origin @token 'IDENTIFIER', 'RegExp', 0, 0 @token 'CALL_START', '(', 0, 0 @mergeInterpolationTokens tokens, {delimiter: '"', double: yes}, @formatHeregex if flags @token ',', ',', index, 0 @token 'STRING', '"' + flags + '"', index, flags.length @token ')', ')', end, 0 @token 'REGEX_END', ')', end, 0 end # Matches newlines, indents, and outdents, and determines which is which. # If we can detect that the current line is continued onto the the next line, # then the newline is suppressed: # # elements # .each( ... ) # .map( ... ) # # Keeps track of the level of indentation, because a single outdent token # can close multiple indents, so we need to know how far in we happen to be. lineToken: -> return 0 unless match = MULTI_DENT.exec @chunk indent = match[0] @seenFor = no size = indent.length - 1 - indent.lastIndexOf '\n' noNewlines = @unfinished() if size - @indebt is @indent if noNewlines then @suppressNewlines() else @newlineToken 0 return indent.length if size > @indent if noNewlines @indebt = size - @indent @suppressNewlines() return indent.length unless @tokens.length @baseIndent = @indent = size return indent.length diff = size - @indent + @outdebt @token 'INDENT', diff, indent.length - size, size @indents.push diff @ends.push {tag: 'OUTDENT'} @outdebt = @indebt = 0 @indent = size else if size < @baseIndent @error 'missing indentation', offset: indent.length else @indebt = 0 @outdentToken @indent - size, noNewlines, indent.length indent.length # Record an outdent token or multiple tokens, if we happen to be moving back # inwards past several recorded indents. Sets new @indent value. outdentToken: (moveOut, noNewlines, outdentLength) -> decreasedIndent = @indent - moveOut while moveOut > 0 lastIndent = @indents[@indents.length - 1] if not lastIndent moveOut = 0 else if lastIndent is @outdebt moveOut -= @outdebt @outdebt = 0 else if lastIndent < @outdebt @outdebt -= lastIndent moveOut -= lastIndent else dent = @indents.pop() + @outdebt if outdentLength and @chunk[outdentLength] in INDENTABLE_CLOSERS decreasedIndent -= dent - moveOut moveOut = dent @outdebt = 0 # pair might call outdentToken, so preserve decreasedIndent @pair 'OUTDENT' @token 'OUTDENT', moveOut, 0, outdentLength moveOut -= dent @outdebt -= moveOut if dent @tokens.pop() while @value() is ';' @token 'TERMINATOR', '\n', outdentLength, 0 unless @tag() is 'TERMINATOR' or noNewlines @indent = decreasedIndent this # Matches and consumes non-meaningful whitespace. Tag the previous token # as being "spaced", because there are some cases where it makes a difference. whitespaceToken: -> return 0 unless (match = WHITESPACE.exec @chunk) or (nline = @chunk.charAt(0) is '\n') [..., prev] = @tokens prev[if match then 'spaced' else 'newLine'] = true if prev if match then match[0].length else 0 # Generate a newline token. Consecutive newlines get merged together. newlineToken: (offset) -> @tokens.pop() while @value() is ';' @token 'TERMINATOR', '\n', offset, 0 unless @tag() is 'TERMINATOR' this # Use a `\` at a line-ending to suppress the newline. # The slash is removed here once its job is done. suppressNewlines: -> @tokens.pop() if @value() is '\\' this # We treat all other single characters as a token. E.g.: `( ) , . !` # Multi-character operators are also literal tokens, so that Jison can assign # the proper order of operations. There are some symbols that we tag specially # here. `;` and newlines are both treated as a `TERMINATOR`, we distinguish # parentheses that indicate a method call from regular parentheses, and so on. literalToken: -> if match = OPERATOR.exec @chunk [value] = match @tagParameters() if CODE.test value else value = @chunk.charAt 0 tag = value [..., prev] = @tokens if value is '=' and prev if not prev[1].reserved and prev[1] in JS_FORBIDDEN prev = prev.origin if prev.origin @error "reserved word '#{prev[1]}' can't be assigned", prev[2] if prev[1] in ['||', '&&'] prev[0] = 'COMPOUND_ASSIGN' prev[1] += '=' return value.length if value is ';' @seenFor = no tag = 'TERMINATOR' else if value in MATH then tag = 'MATH' else if value in COMPARE then tag = 'COMPARE' else if value in COMPOUND_ASSIGN then tag = 'COMPOUND_ASSIGN' else if value in UNARY then tag = 'UNARY' else if value in UNARY_MATH then tag = 'UNARY_MATH' else if value in SHIFT then tag = 'SHIFT' else if value in LOGIC or value is '?' and prev?.spaced then tag = 'LOGIC' else if prev and not prev.spaced if value is '(' and prev[0] in CALLABLE prev[0] = 'FUNC_EXIST' if prev[0] is '?' tag = 'CALL_START' else if value is '[' and prev[0] in INDEXABLE tag = 'INDEX_START' switch prev[0] when '?' then prev[0] = 'INDEX_SOAK' token = @makeToken tag, value switch value when '(', '{', '[' then @ends.push {tag: INVERSES[value], origin: token} when ')', '}', ']' then @pair value @tokens.push token value.length # Token Manipulators # ------------------ # A source of ambiguity in our grammar used to be parameter lists in function # definitions versus argument lists in function calls. Walk backwards, tagging # parameters specially in order to make things easier for the parser. tagParameters: -> return this if @tag() isnt ')' stack = [] {tokens} = this i = tokens.length tokens[--i][0] = 'PARAM_END' while tok = tokens[--i] switch tok[0] when ')' stack.push tok when '(', 'CALL_START' if stack.length then stack.pop() else if tok[0] is '(' tok[0] = 'PARAM_START' return this else return this this # Close up all remaining open blocks at the end of the file. closeIndentation: -> @outdentToken @indent # Match the contents of a delimited token and expand variables and expressions # inside it using Ruby-like notation for substitution of arbitrary # expressions. # # "Hello #{name.capitalize()}." # # If it encounters an interpolation, this method will recursively create a new # Lexer and tokenize until the `{` of `#{` is balanced with a `}`. # # - `regex` matches the contents of a token (but not `delimiter`, and not # `#{` if interpolations are desired). # - `delimiter` is the delimiter of the token. Examples are `'`, `"`, `'''`, # `"""` and `///`. # # This method allows us to have strings within interpolations within strings, # ad infinitum. matchWithInterpolations: (regex, delimiter) -> tokens = [] offsetInChunk = delimiter.length return null unless @chunk[...offsetInChunk] is delimiter str = @chunk[offsetInChunk..] loop [strPart] = regex.exec str @validateEscapes strPart, {isRegex: delimiter.charAt(0) is '/', offsetInChunk} # Push a fake 'NEOSTRING' token, which will get turned into a real string later. tokens.push @makeToken 'NEOSTRING', strPart, offsetInChunk str = str[strPart.length..] offsetInChunk += strPart.length break unless str[...2] is '#{' # The `1`s are to remove the `#` in `#{`. [line, column] = @getLineAndColumnFromChunk offsetInChunk + 1 {tokens: nested, index} = new Lexer().tokenize str[1..], line: line, column: column, untilBalanced: on # Skip the trailing `}`. index += 1 # Turn the leading and trailing `{` and `}` into parentheses. Unnecessary # parentheses will be removed later. [open, ..., close] = nested open[0] = open[1] = '(' close[0] = close[1] = ')' close.origin = ['', 'end of interpolation', close[2]] # Remove leading 'TERMINATOR' (if any). nested.splice 1, 1 if nested[1]?[0] is 'TERMINATOR' # Push a fake 'TOKENS' token, which will get turned into real tokens later. tokens.push ['TOKENS', nested] str = str[index..] offsetInChunk += index unless str[...delimiter.length] is delimiter @error "missing #{delimiter}", length: delimiter.length [firstToken, ..., lastToken] = tokens firstToken[2].first_column -= delimiter.length lastToken[2].last_column += delimiter.length lastToken[2].last_column -= 1 if lastToken[1].length is 0 {tokens, index: offsetInChunk + delimiter.length} # Merge the array `tokens` of the fake token types 'TOKENS' and 'NEOSTRING' # (as returned by `matchWithInterpolations`) into the token stream. The value # of 'NEOSTRING's are converted using `fn` and turned into strings using # `options` first. mergeInterpolationTokens: (tokens, options, fn) -> if tokens.length > 1 lparen = @token 'STRING_START', '(', 0, 0 firstIndex = @tokens.length for token, i in tokens [tag, value] = token switch tag when 'TOKENS' # Optimize out empty interpolations (an empty pair of parentheses). continue if value.length is 2 # Push all the tokens in the fake 'TOKENS' token. These already have # sane location data. locationToken = value[0] tokensToPush = value when 'NEOSTRING' # Convert 'NEOSTRING' into 'STRING'. converted = fn token[1], i # Optimize out empty strings. We ensure that the tokens stream always # starts with a string token, though, to make sure that the result # really is a string. if converted.length is 0 if i is 0 firstEmptyStringIndex = @tokens.length else continue # However, there is one case where we can optimize away a starting # empty string. if i is 2 and firstEmptyStringIndex? @tokens.splice firstEmptyStringIndex, 2 # Remove empty string and the plus. token[0] = 'STRING' token[1] = @makeDelimitedLiteral converted, options locationToken = token tokensToPush = [token] if @tokens.length > firstIndex # Create a 0-length "+" token. plusToken = @token '+', '+' plusToken[2] = first_line: locationToken[2].first_line first_column: locationToken[2].first_column last_line: locationToken[2].first_line last_column: locationToken[2].first_column @tokens.push tokensToPush... if lparen [..., lastToken] = tokens lparen.origin = ['STRING', null, first_line: lparen[2].first_line first_column: lparen[2].first_column last_line: lastToken[2].last_line last_column: lastToken[2].last_column ] rparen = @token 'STRING_END', ')' rparen[2] = first_line: lastToken[2].last_line first_column: lastToken[2].last_column last_line: lastToken[2].last_line last_column: lastToken[2].last_column # Pairs up a closing token, ensuring that all listed pairs of tokens are # correctly balanced throughout the course of the token stream. pair: (tag) -> [..., prev] = @ends unless tag is wanted = prev?.tag @error "unmatched #{tag}" unless 'OUTDENT' is wanted # Auto-close INDENT to support syntax like this: # # el.click((event) -> # el.hide()) # [..., lastIndent] = @indents @outdentToken lastIndent, true return @pair tag @ends.pop() # Helpers # ------- # Returns the line and column number from an offset into the current chunk. # # `offset` is a number of characters into @chunk. getLineAndColumnFromChunk: (offset) -> if offset is 0 return [@chunkLine, @chunkColumn] if offset >= @chunk.length string = @chunk else string = @chunk[..offset-1] lineCount = count string, '\n' column = @chunkColumn if lineCount > 0 [..., lastLine] = string.split '\n' column = lastLine.length else column += string.length [@chunkLine + lineCount, column] # Same as "token", exception this just returns the token without adding it # to the results. makeToken: (tag, value, offsetInChunk = 0, length = value.length) -> locationData = {} [locationData.first_line, locationData.first_column] = @getLineAndColumnFromChunk offsetInChunk # Use length - 1 for the final offset - we're supplying the last_line and the last_column, # so if last_column == first_column, then we're looking at a character of length 1. lastCharacter = Math.max 0, length - 1 [locationData.last_line, locationData.last_column] = @getLineAndColumnFromChunk offsetInChunk + lastCharacter token = [tag, value, locationData] token # Add a token to the results. # `offset` is the offset into the current @chunk where the token starts. # `length` is the length of the token in the @chunk, after the offset. If # not specified, the length of `value` will be used. # # Returns the new token. token: (tag, value, offsetInChunk, length, origin) -> token = @makeToken tag, value, offsetInChunk, length token.origin = origin if origin @tokens.push token token # Peek at the last tag in the token stream. tag: -> [..., token] = @tokens token?[0] # Peek at the last value in the token stream. value: -> [..., token] = @tokens token?[1] # Are we in the midst of an unfinished expression? unfinished: -> LINE_CONTINUER.test(@chunk) or @tag() in ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-', 'YIELD', '**', 'SHIFT', 'RELATION', 'COMPARE', 'LOGIC', 'THROW', 'EXTENDS'] formatString: (str) -> str.replace STRING_OMIT, '$1' formatHeregex: (str) -> str.replace HEREGEX_OMIT, '$1$2' # Validates escapes in strings and regexes. validateEscapes: (str, options = {}) -> match = INVALID_ESCAPE.exec str return unless match [[], before, octal, hex, unicode] = match return if options.isRegex and octal and octal.charAt(0) isnt '0' message = if octal "octal escape sequences are not allowed" else "invalid escape sequence" invalidEscape = "\\#{octal or hex or unicode}" @error "#{message} #{invalidEscape}", offset: (options.offsetInChunk ? 0) + match.index + before.length length: invalidEscape.length # Constructs a string or regex by escaping certain characters. makeDelimitedLiteral: (body, options = {}) -> body = '(?:)' if body is '' and options.delimiter is '/' regex = /// (\\\\) # escaped backslash | (\\0(?=[1-7])) # nul character mistaken as octal escape | \\?(#{options.delimiter}) # (possibly escaped) delimiter | \\?(?: (\n)|(\r)|(\u2028)|(\u2029) ) # (possibly escaped) newlines | (\\.) # other escapes ///g body = body.replace regex, (match, backslash, nul, delimiter, lf, cr, ls, ps, other) -> switch # Ignore escaped backslashes. when backslash then (if options.double then backslash + backslash else backslash) when nul then '\\x00' when delimiter then "\\#{delimiter}" when lf then '\\n' when cr then '\\r' when ls then '\\u2028' when ps then '\\u2029' when other then (if options.double then "\\#{other}" else other) "#{options.delimiter}#{body}#{options.delimiter}" # Throws an error at either a given offset from the current chunk or at the # location of a token (`token[2]`). error: (message, options = {}) -> location = if 'first_line' of options options else [first_line, first_column] = @getLineAndColumnFromChunk options.offset ? 0 {first_line, first_column, last_column: first_column + (options.length ? 1) - 1} throwSyntaxError message, location # Constants # --------- # Keywords that CoffeeScript shares in common with JavaScript. JS_KEYWORDS = [ 'true', 'false', 'null', 'this' 'new', 'delete', 'typeof', 'in', 'instanceof' 'return', 'throw', 'break', 'continue', 'debugger', 'yield' 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally' 'class', 'extends', 'super' ] # CoffeeScript-only keywords. COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when'] COFFEE_ALIAS_MAP = and : '&&' or : '||' is : '==' isnt : '!=' not : '!' yes : 'true' no : 'false' on : 'true' off : 'false' COFFEE_ALIASES = (key for key of COFFEE_ALIAS_MAP) COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat COFFEE_ALIASES # The list of keywords that are reserved by JavaScript, but not used, or are # used by CoffeeScript internally. We throw an error when these are encountered, # to avoid having a JavaScript error at runtime. RESERVED = [ 'case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum' 'export', 'import', 'native', 'implements', 'interface', 'package', 'private' 'protected', 'public', 'static' ] STRICT_PROSCRIBED = ['arguments', 'eval', 'yield*'] # The superset of both JavaScript keywords and reserved words, none of which may # be used as identifiers or properties. JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED) exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED) exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED # The character code of the nasty Microsoft madness otherwise known as the BOM. BOM = 65279 # Token matching regexes. IDENTIFIER = /// ^ (?!\d) ( (?: (?!\s)[$\w\x7f-\uffff] )+ ) ( [^\n\S]* : (?!:) )? # Is this a property name? /// NUMBER = /// ^ 0b[01]+ | # binary ^ 0o[0-7]+ | # octal ^ 0x[\da-f]+ | # hex ^ \d*\.?\d+ (?:e[+-]?\d+)? # decimal ///i OPERATOR = /// ^ ( ?: [-=]> # function | [-+*/%<>&|^!?=]= # compound assign / compare | >>>=? # zero-fill right shift | ([-+:])\1 # doubles | ([&|<>*/%])\2=? # logic / shift / power / floor division / modulo | \?(\.|::) # soak access | \.{2,3} # range or splat ) /// WHITESPACE = /^[^\n\S]+/ COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|###$)|^(?:\s*#(?!##[^#]).*)+/ CODE = /^[-=]>/ MULTI_DENT = /^(?:\n[^\n\S]*)+/ JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/ # String-matching-regexes. STRING_START = /^(?:'''|"""|'|")/ STRING_SINGLE = /// ^(?: [^\\'] | \\[\s\S] )* /// STRING_DOUBLE = /// ^(?: [^\\"#] | \\[\s\S] | \#(?!\{) )* /// HEREDOC_SINGLE = /// ^(?: [^\\'] | \\[\s\S] | '(?!'') )* /// HEREDOC_DOUBLE = /// ^(?: [^\\"#] | \\[\s\S] | "(?!"") | \#(?!\{) )* /// STRING_OMIT = /// ((?:\\\\)+) # consume (and preserve) an even number of backslashes | \\[^\S\n]*\n\s* # remove escaped newlines ///g SIMPLE_STRING_OMIT = /\s*\n\s*/g HEREDOC_INDENT = /\n+([^\n\S]*)(?=\S)/g # Regex-matching-regexes. REGEX = /// ^ / (?!/) (( ?: [^ [ / \n \\ ] # every other thing | \\[^\n] # anything but newlines escaped | \[ # character class (?: \\[^\n] | [^ \] \n \\ ] )* \] )*) (/)? /// REGEX_FLAGS = /^\w*/ VALID_FLAGS = /^(?!.*(.).*\1)[imgy]*$/ HEREGEX = /// ^(?: [^\\/#] | \\[\s\S] | /(?!//) | \#(?!\{) )* /// HEREGEX_OMIT = /// ((?:\\\\)+) # consume (and preserve) an even number of backslashes | \\(\s) # preserve escaped whitespace | \s+(?:#.*)? # remove whitespace and comments ///g REGEX_ILLEGAL = /// ^ ( / | /{3}\s*) (\*) /// POSSIBLY_DIVISION = /// ^ /=?\s /// # Other regexes. HERECOMMENT_ILLEGAL = /\*\// LINE_CONTINUER = /// ^ \s* (?: , | \??\.(?![.\d]) | :: ) /// INVALID_ESCAPE = /// ( (?:^|[^\\]) (?:\\\\)* ) # make sure the escape isn’t escaped \\ ( ?: (0[0-7]|[1-7]) # octal escape | (x(?![\da-fA-F]{2}).{0,2}) # hex escape | (u(?![\da-fA-F]{4}).{0,4}) # unicode escape ) /// LEADING_BLANK_LINE = /^[^\n\S]*\n/ TRAILING_BLANK_LINE = /\n[^\n\S]*$/ TRAILING_SPACES = /\s+$/ # Compound assignment tokens. COMPOUND_ASSIGN = [ '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=' '&=', '^=', '|=', '**=', '//=', '%%=' ] # Unary tokens. UNARY = ['NEW', 'TYPEOF', 'DELETE', 'DO'] UNARY_MATH = ['!', '~'] # Logical tokens. LOGIC = ['&&', '||', '&', '|', '^'] # Bit-shifting tokens. SHIFT = ['<<', '>>', '>>>'] # Comparison tokens. COMPARE = ['==', '!=', '<', '>', '<=', '>='] # Mathematical tokens. MATH = ['*', '/', '%', '//', '%%'] # Relational tokens that are negatable with `not` prefix. RELATION = ['IN', 'OF', 'INSTANCEOF'] # Boolean tokens. BOOL = ['TRUE', 'FALSE'] # Tokens which could legitimately be invoked or indexed. An opening # parentheses or bracket following these tokens will be recorded as the start # of a function invocation or indexing operation. CALLABLE = ['IDENTIFIER', ')', ']', '?', '@', 'THIS', 'SUPER'] INDEXABLE = CALLABLE.concat [ 'NUMBER', 'STRING', 'STRING_END', 'REGEX', 'REGEX_END' 'BOOL', 'NULL', 'UNDEFINED', '}', '::' ] # Tokens which a regular expression will never immediately follow (except spaced # CALLABLEs in some cases), but which a division operator can. # # See: http://www-archive.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions NOT_REGEX = INDEXABLE.concat ['++', '--'] # Tokens that, when immediately preceding a `WHEN`, indicate that the `WHEN` # occurs at the start of a line. We disambiguate these from trailing whens to # avoid an ambiguity in the grammar. LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'] # Additional indent in front of these is ignored. INDENTABLE_CLOSERS = [')', '}', ']'] 1.9.3~dfsg/src/command.coffee0000644000000000000000000003647412531364553014671 0ustar rootroot# The `coffee` utility. Handles command-line compilation of CoffeeScript # into various forms: saved into `.js` files or printed to stdout # or recompiled every time the source is saved, # printed as a token stream or as the syntax tree, or launch an # interactive REPL. # External dependencies. fs = require 'fs' path = require 'path' helpers = require './helpers' optparse = require './optparse' CoffeeScript = require './coffee-script' {spawn, exec} = require 'child_process' {EventEmitter} = require 'events' useWinPathSep = path.sep is '\\' # Allow CoffeeScript to emit Node.js events. helpers.extend CoffeeScript, new EventEmitter printLine = (line) -> process.stdout.write line + '\n' printWarn = (line) -> process.stderr.write line + '\n' hidden = (file) -> /^\.|~$/.test file # The help banner that is printed in conjunction with `-h`/`--help`. BANNER = ''' Usage: coffee [options] path/to/script.coffee -- [args] If called without options, `coffee` will run your script. ''' # The list of all the valid option flags that `coffee` knows how to handle. SWITCHES = [ ['-b', '--bare', 'compile without a top-level function wrapper'] ['-c', '--compile', 'compile to JavaScript and save as .js files'] ['-e', '--eval', 'pass a string from the command line as input'] ['-h', '--help', 'display this help message'] ['-i', '--interactive', 'run an interactive CoffeeScript REPL'] ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'] ['-m', '--map', 'generate source map and save as .js.map files'] ['-n', '--nodes', 'print out the parse tree that the parser produces'] [ '--nodejs [ARGS]', 'pass options directly to the "node" binary'] [ '--no-header', 'suppress the "Generated by" header'] ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'] ['-p', '--print', 'print out the compiled JavaScript'] ['-r', '--require [MODULE*]', 'require the given module before eval or REPL'] ['-s', '--stdio', 'listen for and compile scripts over stdio'] ['-l', '--literate', 'treat stdio as literate style coffee-script'] ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'] ['-v', '--version', 'display the version number'] ['-w', '--watch', 'watch scripts for changes and rerun commands'] ] # Top-level objects shared by all the functions. opts = {} sources = [] sourceCode = [] notSources = {} watchedDirs = {} optionParser = null # Run `coffee` by parsing passed options and determining what action to take. # Many flags cause us to divert before compiling anything. Flags passed after # `--` will be passed verbatim to your script as arguments in `process.argv` exports.run = -> parseOptions() # Make the REPL *CLI* use the global context so as to (a) be consistent with the # `node` REPL CLI and, therefore, (b) make packages that modify native prototypes # (such as 'colors' and 'sugar') work as expected. replCliOpts = useGlobal: yes opts.prelude = makePrelude opts.require if opts.require replCliOpts.prelude = opts.prelude return forkNode() if opts.nodejs return usage() if opts.help return version() if opts.version return require('./repl').start(replCliOpts) if opts.interactive return compileStdio() if opts.stdio return compileScript null, opts.arguments[0] if opts.eval return require('./repl').start(replCliOpts) unless opts.arguments.length literals = if opts.run then opts.arguments.splice 1 else [] process.argv = process.argv[0..1].concat literals process.argv[0] = 'coffee' opts.output = path.resolve opts.output if opts.output if opts.join opts.join = path.resolve opts.join console.error ''' The --join option is deprecated and will be removed in a future version. If for some reason it's necessary to share local variables between files, replace... $ coffee --compile --join bundle.js -- a.coffee b.coffee c.coffee with... $ cat a.coffee b.coffee c.coffee | coffee --compile --stdio > bundle.js ''' for source in opts.arguments source = path.resolve source compilePath source, yes, source makePrelude = (requires) -> requires.map (module) -> [_, name, module] = match if match = module.match(/^(.*)=(.*)$/) name ||= helpers.baseFileName module, yes, useWinPathSep "#{name} = require('#{module}')" .join ';' # Compile a path, which could be a script or a directory. If a directory # is passed, recursively compile all '.coffee', '.litcoffee', and '.coffee.md' # extension source files in it and all subdirectories. compilePath = (source, topLevel, base) -> return if source in sources or watchedDirs[source] or not topLevel and (notSources[source] or hidden source) try stats = fs.statSync source catch err if err.code is 'ENOENT' console.error "File not found: #{source}" process.exit 1 throw err if stats.isDirectory() if path.basename(source) is 'node_modules' notSources[source] = yes return if opts.run compilePath findDirectoryIndex(source), topLevel, base return watchDir source, base if opts.watch try files = fs.readdirSync source catch err if err.code is 'ENOENT' then return else throw err for file in files compilePath (path.join source, file), no, base else if topLevel or helpers.isCoffee source sources.push source sourceCode.push null delete notSources[source] watch source, base if opts.watch try code = fs.readFileSync source catch err if err.code is 'ENOENT' then return else throw err compileScript(source, code.toString(), base) else notSources[source] = yes findDirectoryIndex = (source) -> for ext in CoffeeScript.FILE_EXTENSIONS index = path.join source, "index#{ext}" try return index if (fs.statSync index).isFile() catch err throw err unless err.code is 'ENOENT' console.error "Missing index.coffee or index.litcoffee in #{source}" process.exit 1 # Compile a single source script, containing the given code, according to the # requested options. If evaluating the script directly sets `__filename`, # `__dirname` and `module.filename` to be correct relative to the script's path. compileScript = (file, input, base = null) -> o = opts options = compileOptions file, base try t = task = {file, input, options} CoffeeScript.emit 'compile', task if o.tokens printTokens CoffeeScript.tokens t.input, t.options else if o.nodes printLine CoffeeScript.nodes(t.input, t.options).toString().trim() else if o.run CoffeeScript.register() CoffeeScript.eval opts.prelude, t.options if opts.prelude CoffeeScript.run t.input, t.options else if o.join and t.file isnt o.join t.input = helpers.invertLiterate t.input if helpers.isLiterate file sourceCode[sources.indexOf(t.file)] = t.input compileJoin() else compiled = CoffeeScript.compile t.input, t.options t.output = compiled if o.map t.output = compiled.js t.sourceMap = compiled.v3SourceMap CoffeeScript.emit 'success', task if o.print printLine t.output.trim() else if o.compile or o.map writeJs base, t.file, t.output, options.jsPath, t.sourceMap catch err CoffeeScript.emit 'failure', err, task return if CoffeeScript.listeners('failure').length message = err.stack or "#{err}" if o.watch printLine message + '\x07' else printWarn message process.exit 1 # Attach the appropriate listeners to compile scripts incoming over **stdin**, # and write them back to **stdout**. compileStdio = -> code = '' stdin = process.openStdin() stdin.on 'data', (buffer) -> code += buffer.toString() if buffer stdin.on 'end', -> compileScript null, code # If all of the source files are done being read, concatenate and compile # them together. joinTimeout = null compileJoin = -> return unless opts.join unless sourceCode.some((code) -> code is null) clearTimeout joinTimeout joinTimeout = wait 100, -> compileScript opts.join, sourceCode.join('\n'), opts.join # Watch a source CoffeeScript file using `fs.watch`, recompiling it every # time the file is updated. May be used in combination with other options, # such as `--print`. watch = (source, base) -> watcher = null prevStats = null compileTimeout = null watchErr = (err) -> throw err unless err.code is 'ENOENT' return unless source in sources try rewatch() compile() catch removeSource source, base compileJoin() compile = -> clearTimeout compileTimeout compileTimeout = wait 25, -> fs.stat source, (err, stats) -> return watchErr err if err return rewatch() if prevStats and stats.size is prevStats.size and stats.mtime.getTime() is prevStats.mtime.getTime() prevStats = stats fs.readFile source, (err, code) -> return watchErr err if err compileScript(source, code.toString(), base) rewatch() startWatcher = -> watcher = fs.watch source .on 'change', compile .on 'error', (err) -> throw err unless err.code is 'EPERM' removeSource source, base rewatch = -> watcher?.close() startWatcher() try startWatcher() catch err watchErr err # Watch a directory of files for new additions. watchDir = (source, base) -> watcher = null readdirTimeout = null startWatcher = -> watcher = fs.watch source .on 'error', (err) -> throw err unless err.code is 'EPERM' stopWatcher() .on 'change', -> clearTimeout readdirTimeout readdirTimeout = wait 25, -> try files = fs.readdirSync source catch err throw err unless err.code is 'ENOENT' return stopWatcher() for file in files compilePath (path.join source, file), no, base stopWatcher = -> watcher.close() removeSourceDir source, base watchedDirs[source] = yes try startWatcher() catch err throw err unless err.code is 'ENOENT' removeSourceDir = (source, base) -> delete watchedDirs[source] sourcesChanged = no for file in sources when source is path.dirname file removeSource file, base sourcesChanged = yes compileJoin() if sourcesChanged # Remove a file from our source list, and source code cache. Optionally remove # the compiled JS version as well. removeSource = (source, base) -> index = sources.indexOf source sources.splice index, 1 sourceCode.splice index, 1 unless opts.join silentUnlink outputPath source, base silentUnlink outputPath source, base, '.js.map' timeLog "removed #{source}" silentUnlink = (path) -> try fs.unlinkSync path catch err throw err unless err.code in ['ENOENT', 'EPERM'] # Get the corresponding output JavaScript path for a source file. outputPath = (source, base, extension=".js") -> basename = helpers.baseFileName source, yes, useWinPathSep srcDir = path.dirname source if not opts.output dir = srcDir else if source is base dir = opts.output else dir = path.join opts.output, path.relative base, srcDir path.join dir, basename + extension # Recursively mkdir, like `mkdir -p`. mkdirp = (dir, fn) -> mode = 0o777 & ~process.umask() do mkdirs = (p = dir, fn) -> fs.exists p, (exists) -> if exists fn() else mkdirs path.dirname(p), -> fs.mkdir p, mode, (err) -> return fn err if err fn() # Write out a JavaScript source file with the compiled code. By default, files # are written out in `cwd` as `.js` files with the same name, but the output # directory can be customized with `--output`. # # If `generatedSourceMap` is provided, this will write a `.js.map` file into the # same directory as the `.js` file. writeJs = (base, sourcePath, js, jsPath, generatedSourceMap = null) -> sourceMapPath = outputPath sourcePath, base, ".js.map" jsDir = path.dirname jsPath compile = -> if opts.compile js = ' ' if js.length <= 0 if generatedSourceMap then js = "#{js}\n//# sourceMappingURL=#{helpers.baseFileName sourceMapPath, no, useWinPathSep}\n" fs.writeFile jsPath, js, (err) -> if err printLine err.message process.exit 1 else if opts.compile and opts.watch timeLog "compiled #{sourcePath}" if generatedSourceMap fs.writeFile sourceMapPath, generatedSourceMap, (err) -> if err printLine "Could not write source map: #{err.message}" process.exit 1 fs.exists jsDir, (itExists) -> if itExists then compile() else mkdirp jsDir, compile # Convenience for cleaner setTimeouts. wait = (milliseconds, func) -> setTimeout func, milliseconds # When watching scripts, it's useful to log changes with the timestamp. timeLog = (message) -> console.log "#{(new Date).toLocaleTimeString()} - #{message}" # Pretty-print a stream of tokens, sans location data. printTokens = (tokens) -> strings = for token in tokens tag = token[0] value = token[1].toString().replace(/\n/, '\\n') "[#{tag} #{value}]" printLine strings.join(' ') # Use the [OptionParser module](optparse.html) to extract all options from # `process.argv` that are specified in `SWITCHES`. parseOptions = -> optionParser = new optparse.OptionParser SWITCHES, BANNER o = opts = optionParser.parse process.argv[2..] o.compile or= !!o.output o.run = not (o.compile or o.print or o.map) o.print = !! (o.print or (o.eval or o.stdio and o.compile)) # The compile-time options to pass to the CoffeeScript compiler. compileOptions = (filename, base) -> answer = { filename literate: opts.literate or helpers.isLiterate(filename) bare: opts.bare header: opts.compile and not opts['no-header'] sourceMap: opts.map } if filename if base cwd = process.cwd() jsPath = outputPath filename, base jsDir = path.dirname jsPath answer = helpers.merge answer, { jsPath sourceRoot: path.relative jsDir, cwd sourceFiles: [path.relative cwd, filename] generatedFile: helpers.baseFileName(jsPath, no, useWinPathSep) } else answer = helpers.merge answer, sourceRoot: "" sourceFiles: [helpers.baseFileName filename, no, useWinPathSep] generatedFile: helpers.baseFileName(filename, yes, useWinPathSep) + ".js" answer # Start up a new Node.js instance with the arguments in `--nodejs` passed to # the `node` binary, preserving the other options. forkNode = -> nodeArgs = opts.nodejs.split /\s+/ args = process.argv[1..] args.splice args.indexOf('--nodejs'), 2 p = spawn process.execPath, nodeArgs.concat(args), cwd: process.cwd() env: process.env stdio: [0, 1, 2] p.on 'exit', (code) -> process.exit code # Print the `--help` usage message and exit. Deprecated switches are not # shown. usage = -> printLine (new optparse.OptionParser SWITCHES, BANNER).help() # Print the `--version` message and exit. version = -> printLine "CoffeeScript version #{CoffeeScript.VERSION}" 1.9.3~dfsg/src/rewriter.coffee0000644000000000000000000004374012531364553015110 0ustar rootroot# The CoffeeScript language has a good deal of optional syntax, implicit syntax, # and shorthand syntax. This can greatly complicate a grammar and bloat # the resulting parse table. Instead of making the parser handle it all, we take # a series of passes over the token stream, using this **Rewriter** to convert # shorthand into the unambiguous long form, add implicit indentation and # parentheses, and generally clean things up. # Create a generated token: one that exists due to a use of implicit syntax. generate = (tag, value, origin) -> tok = [tag, value] tok.generated = yes tok.origin = origin if origin tok # The **Rewriter** class is used by the [Lexer](lexer.html), directly against # its internal array of tokens. class exports.Rewriter # Helpful snippet for debugging: # # console.log (t[0] + '/' + t[1] for t in @tokens).join ' ' # Rewrite the token stream in multiple passes, one logical filter at # a time. This could certainly be changed into a single pass through the # stream, with a big ol' efficient switch, but it's much nicer to work with # like this. The order of these passes matters -- indentation must be # corrected before implicit parentheses can be wrapped around blocks of code. rewrite: (@tokens) -> @removeLeadingNewlines() @closeOpenCalls() @closeOpenIndexes() @normalizeLines() @tagPostfixConditionals() @addImplicitBracesAndParens() @addLocationDataToGeneratedTokens() @tokens # Rewrite the token stream, looking one token ahead and behind. # Allow the return value of the block to tell us how many tokens to move # forwards (or backwards) in the stream, to make sure we don't miss anything # as tokens are inserted and removed, and the stream changes length under # our feet. scanTokens: (block) -> {tokens} = this i = 0 i += block.call this, token, i, tokens while token = tokens[i] true detectEnd: (i, condition, action) -> {tokens} = this levels = 0 while token = tokens[i] return action.call this, token, i if levels is 0 and condition.call this, token, i return action.call this, token, i - 1 if not token or levels < 0 if token[0] in EXPRESSION_START levels += 1 else if token[0] in EXPRESSION_END levels -= 1 i += 1 i - 1 # Leading newlines would introduce an ambiguity in the grammar, so we # dispatch them here. removeLeadingNewlines: -> break for [tag], i in @tokens when tag isnt 'TERMINATOR' @tokens.splice 0, i if i # The lexer has tagged the opening parenthesis of a method call. Match it with # its paired close. We have the mis-nested outdent case included here for # calls that close on the same line, just before their outdent. closeOpenCalls: -> condition = (token, i) -> token[0] in [')', 'CALL_END'] or token[0] is 'OUTDENT' and @tag(i - 1) is ')' action = (token, i) -> @tokens[if token[0] is 'OUTDENT' then i - 1 else i][0] = 'CALL_END' @scanTokens (token, i) -> @detectEnd i + 1, condition, action if token[0] is 'CALL_START' 1 # The lexer has tagged the opening parenthesis of an indexing operation call. # Match it with its paired close. closeOpenIndexes: -> condition = (token, i) -> token[0] in [']', 'INDEX_END'] action = (token, i) -> token[0] = 'INDEX_END' @scanTokens (token, i) -> @detectEnd i + 1, condition, action if token[0] is 'INDEX_START' 1 # Match tags in token stream starting at `i` with `pattern`, skipping 'HERECOMMENT's. # `pattern` may consist of strings (equality), an array of strings (one of) # or null (wildcard). Returns the index of the match or -1 if no match. indexOfTag: (i, pattern...) -> fuzz = 0 for j in [0 ... pattern.length] fuzz += 2 while @tag(i + j + fuzz) is 'HERECOMMENT' continue if not pattern[j]? pattern[j] = [pattern[j]] if typeof pattern[j] is 'string' return -1 if @tag(i + j + fuzz) not in pattern[j] i + j + fuzz - 1 # Returns `yes` if standing in front of something looking like # `@:`, `:` or `...:`, # skipping over 'HERECOMMENT's. looksObjectish: (j) -> return yes if @indexOfTag(j, '@', null, ':') > -1 or @indexOfTag(j, null, ':') > -1 index = @indexOfTag(j, EXPRESSION_START) if index > -1 end = null @detectEnd index + 1, ((token) -> token[0] in EXPRESSION_END), ((token, i) -> end = i) return yes if @tag(end + 1) is ':' no # Returns `yes` if current line of tokens contain an element of tags on same # expression level. Stop searching at LINEBREAKS or explicit start of # containing balanced expression. findTagsBackwards: (i, tags) -> backStack = [] while i >= 0 and (backStack.length or @tag(i) not in tags and (@tag(i) not in EXPRESSION_START or @tokens[i].generated) and @tag(i) not in LINEBREAKS) backStack.push @tag(i) if @tag(i) in EXPRESSION_END backStack.pop() if @tag(i) in EXPRESSION_START and backStack.length i -= 1 @tag(i) in tags # Look for signs of implicit calls and objects in the token stream and # add them. addImplicitBracesAndParens: -> # Track current balancing depth (both implicit and explicit) on stack. stack = [] start = null @scanTokens (token, i, tokens) -> [tag] = token [prevTag] = prevToken = if i > 0 then tokens[i - 1] else [] [nextTag] = if i < tokens.length - 1 then tokens[i + 1] else [] stackTop = -> stack[stack.length - 1] startIdx = i # Helper function, used for keeping track of the number of tokens consumed # and spliced, when returning for getting a new token. forward = (n) -> i - startIdx + n # Helper functions inImplicit = -> stackTop()?[2]?.ours inImplicitCall = -> inImplicit() and stackTop()?[0] is '(' inImplicitObject = -> inImplicit() and stackTop()?[0] is '{' # Unclosed control statement inside implicit parens (like # class declaration or if-conditionals) inImplicitControl = -> inImplicit and stackTop()?[0] is 'CONTROL' startImplicitCall = (j) -> idx = j ? i stack.push ['(', idx, ours: yes] tokens.splice idx, 0, generate 'CALL_START', '(' i += 1 if not j? endImplicitCall = -> stack.pop() tokens.splice i, 0, generate 'CALL_END', ')', ['', 'end of input', token[2]] i += 1 startImplicitObject = (j, startsLine = yes) -> idx = j ? i stack.push ['{', idx, sameLine: yes, startsLine: startsLine, ours: yes] val = new String '{' val.generated = yes tokens.splice idx, 0, generate '{', val, token i += 1 if not j? endImplicitObject = (j) -> j = j ? i stack.pop() tokens.splice j, 0, generate '}', '}', token i += 1 # Don't end an implicit call on next indent if any of these are in an argument if inImplicitCall() and tag in ['IF', 'TRY', 'FINALLY', 'CATCH', 'CLASS', 'SWITCH'] stack.push ['CONTROL', i, ours: true] return forward(1) if tag is 'INDENT' and inImplicit() # An `INDENT` closes an implicit call unless # # 1. We have seen a `CONTROL` argument on the line. # 2. The last token before the indent is part of the list below # if prevTag not in ['=>', '->', '[', '(', ',', '{', 'TRY', 'ELSE', '='] endImplicitCall() while inImplicitCall() stack.pop() if inImplicitControl() stack.push [tag, i] return forward(1) # Straightforward start of explicit expression if tag in EXPRESSION_START stack.push [tag, i] return forward(1) # Close all implicit expressions inside of explicitly closed expressions. if tag in EXPRESSION_END while inImplicit() if inImplicitCall() endImplicitCall() else if inImplicitObject() endImplicitObject() else stack.pop() start = stack.pop() # Recognize standard implicit calls like # f a, f() b, f? c, h[0] d etc. if (tag in IMPLICIT_FUNC and token.spaced or tag is '?' and i > 0 and not tokens[i - 1].spaced) and (nextTag in IMPLICIT_CALL or nextTag in IMPLICIT_UNSPACED_CALL and not tokens[i + 1]?.spaced and not tokens[i + 1]?.newLine) tag = token[0] = 'FUNC_EXIST' if tag is '?' startImplicitCall i + 1 return forward(2) # Implicit call taking an implicit indented object as first argument. # # f # a: b # c: d # # and # # f # 1 # a: b # b: c # # Don't accept implicit calls of this type, when on the same line # as the control strucutures below as that may misinterpret constructs like: # # if f # a: 1 # as # # if f(a: 1) # # which is probably always unintended. # Furthermore don't allow this in literal arrays, as # that creates grammatical ambiguities. if tag in IMPLICIT_FUNC and @indexOfTag(i + 1, 'INDENT') > -1 and @looksObjectish(i + 2) and not @findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL']) startImplicitCall i + 1 stack.push ['INDENT', i + 2] return forward(3) # Implicit objects start here if tag is ':' # Go back to the (implicit) start of the object s = switch when @tag(i - 1) in EXPRESSION_END then start[1] when @tag(i - 2) is '@' then i - 2 else i - 1 s -= 2 while @tag(s - 2) is 'HERECOMMENT' # Mark if the value is a for loop @insideForDeclaration = nextTag is 'FOR' startsLine = s is 0 or @tag(s - 1) in LINEBREAKS or tokens[s - 1].newLine # Are we just continuing an already declared object? if stackTop() [stackTag, stackIdx] = stackTop() if (stackTag is '{' or stackTag is 'INDENT' and @tag(stackIdx - 1) is '{') and (startsLine or @tag(s - 1) is ',' or @tag(s - 1) is '{') return forward(1) startImplicitObject(s, !!startsLine) return forward(2) # End implicit calls when chaining method calls # like e.g.: # # f -> # a # .g b, -> # c # .h a # # and also # # f a # .g b # .h a stackTop()[2].sameLine = no if inImplicitObject() and tag in LINEBREAKS newLine = prevTag is 'OUTDENT' or prevToken.newLine if tag in IMPLICIT_END or tag in CALL_CLOSERS and newLine while inImplicit() [stackTag, stackIdx, {sameLine, startsLine}] = stackTop() # Close implicit calls when reached end of argument list if inImplicitCall() and prevTag isnt ',' endImplicitCall() # Close implicit objects such as: # return a: 1, b: 2 unless true else if inImplicitObject() and not @insideForDeclaration and sameLine and tag isnt 'TERMINATOR' and prevTag isnt ':' endImplicitObject() # Close implicit objects when at end of line, line didn't end with a comma # and the implicit object didn't start the line or the next line doesn't look like # the continuation of an object. else if inImplicitObject() and tag is 'TERMINATOR' and prevTag isnt ',' and not (startsLine and @looksObjectish(i + 1)) return forward 1 if nextTag is 'HERECOMMENT' endImplicitObject() else break # Close implicit object if comma is the last character # and what comes after doesn't look like it belongs. # This is used for trailing commas and calls, like: # # x = # a: b, # c: d, # e = 2 # # and # # f a, b: c, d: e, f, g: h: i, j # if tag is ',' and not @looksObjectish(i + 1) and inImplicitObject() and not @insideForDeclaration and (nextTag isnt 'TERMINATOR' or not @looksObjectish(i + 2)) # When nextTag is OUTDENT the comma is insignificant and # should just be ignored so embed it in the implicit object. # # When it isn't the comma go on to play a role in a call or # array further up the stack, so give it a chance. offset = if nextTag is 'OUTDENT' then 1 else 0 while inImplicitObject() endImplicitObject i + offset return forward(1) # Add location data to all tokens generated by the rewriter. addLocationDataToGeneratedTokens: -> @scanTokens (token, i, tokens) -> return 1 if token[2] return 1 unless token.generated or token.explicit if token[0] is '{' and nextLocation=tokens[i + 1]?[2] {first_line: line, first_column: column} = nextLocation else if prevLocation = tokens[i - 1]?[2] {last_line: line, last_column: column} = prevLocation else line = column = 0 token[2] = first_line: line first_column: column last_line: line last_column: column return 1 # Because our grammar is LALR(1), it can't handle some single-line # expressions that lack ending delimiters. The **Rewriter** adds the implicit # blocks, so it doesn't need to. To keep the grammar clean and tidy, trailing # newlines within expressions are removed and the indentation tokens of empty # blocks are added. normalizeLines: -> starter = indent = outdent = null condition = (token, i) -> token[1] isnt ';' and token[0] in SINGLE_CLOSERS and not (token[0] is 'TERMINATOR' and @tag(i + 1) in EXPRESSION_CLOSE) and not (token[0] is 'ELSE' and starter isnt 'THEN') and not (token[0] in ['CATCH', 'FINALLY'] and starter in ['->', '=>']) or token[0] in CALL_CLOSERS and @tokens[i - 1].newLine action = (token, i) -> @tokens.splice (if @tag(i - 1) is ',' then i - 1 else i), 0, outdent @scanTokens (token, i, tokens) -> [tag] = token if tag is 'TERMINATOR' if @tag(i + 1) is 'ELSE' and @tag(i - 1) isnt 'OUTDENT' tokens.splice i, 1, @indentation()... return 1 if @tag(i + 1) in EXPRESSION_CLOSE tokens.splice i, 1 return 0 if tag is 'CATCH' for j in [1..2] when @tag(i + j) in ['OUTDENT', 'TERMINATOR', 'FINALLY'] tokens.splice i + j, 0, @indentation()... return 2 + j if tag in SINGLE_LINERS and @tag(i + 1) isnt 'INDENT' and not (tag is 'ELSE' and @tag(i + 1) is 'IF') starter = tag [indent, outdent] = @indentation tokens[i] indent.fromThen = true if starter is 'THEN' tokens.splice i + 1, 0, indent @detectEnd i + 2, condition, action tokens.splice i, 1 if tag is 'THEN' return 1 return 1 # Tag postfix conditionals as such, so that we can parse them with a # different precedence. tagPostfixConditionals: -> original = null condition = (token, i) -> [tag] = token [prevTag] = @tokens[i - 1] tag is 'TERMINATOR' or (tag is 'INDENT' and prevTag not in SINGLE_LINERS) action = (token, i) -> if token[0] isnt 'INDENT' or (token.generated and not token.fromThen) original[0] = 'POST_' + original[0] @scanTokens (token, i) -> return 1 unless token[0] is 'IF' original = token @detectEnd i + 1, condition, action return 1 # Generate the indentation tokens, based on another token on the same line. indentation: (origin) -> indent = ['INDENT', 2] outdent = ['OUTDENT', 2] if origin indent.generated = outdent.generated = yes indent.origin = outdent.origin = origin else indent.explicit = outdent.explicit = yes [indent, outdent] generate: generate # Look up a tag by token index. tag: (i) -> @tokens[i]?[0] # Constants # --------- # List of the token pairs that must be balanced. BALANCED_PAIRS = [ ['(', ')'] ['[', ']'] ['{', '}'] ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'] ['PARAM_START', 'PARAM_END'] ['INDEX_START', 'INDEX_END'] ['STRING_START', 'STRING_END'] ['REGEX_START', 'REGEX_END'] ] # The inverse mappings of `BALANCED_PAIRS` we're trying to fix up, so we can # look things up from either end. exports.INVERSES = INVERSES = {} # The tokens that signal the start/end of a balanced pair. EXPRESSION_START = [] EXPRESSION_END = [] for [left, rite] in BALANCED_PAIRS EXPRESSION_START.push INVERSES[rite] = left EXPRESSION_END .push INVERSES[left] = rite # Tokens that indicate the close of a clause of an expression. EXPRESSION_CLOSE = ['CATCH', 'THEN', 'ELSE', 'FINALLY'].concat EXPRESSION_END # Tokens that, if followed by an `IMPLICIT_CALL`, indicate a function invocation. IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'] # If preceded by an `IMPLICIT_FUNC`, indicates a function invocation. IMPLICIT_CALL = [ 'IDENTIFIER', 'NUMBER', 'STRING', 'STRING_START', 'JS', 'REGEX', 'REGEX_START' 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL' 'UNDEFINED', 'UNARY', 'YIELD', 'UNARY_MATH', 'SUPER', 'THROW' '@', '->', '=>', '[', '(', '{', '--', '++' ] IMPLICIT_UNSPACED_CALL = ['+', '-'] # Tokens that always mark the end of an implicit call for single-liners. IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'] # Single-line flavors of block expressions that have unclosed endings. # The grammar can't disambiguate them, so we insert the implicit indentation. SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'] SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'] # Tokens that end a line. LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'] # Tokens that close open calls when they follow a newline. CALL_CLOSERS = ['.', '?.', '::', '?::'] 1.9.3~dfsg/src/scope.litcoffee0000644000000000000000000000752612531364553015071 0ustar rootrootThe **Scope** class regulates lexical scoping within CoffeeScript. As you generate code, you create a tree of scopes in the same shape as the nested function bodies. Each scope knows about the variables declared within it, and has a reference to its parent enclosing scope. In this way, we know which variables are new and need to be declared with `var`, and which are shared with external scopes. exports.Scope = class Scope Initialize a scope with its parent, for lookups up the chain, as well as a reference to the **Block** node it belongs to, which is where it should declare its variables, a reference to the function that it belongs to, and a list of variables referenced in the source code and therefore should be avoided when generating variables. constructor: (@parent, @expressions, @method, @referencedVars) -> @variables = [{name: 'arguments', type: 'arguments'}] @positions = {} @utilities = {} unless @parent The `@root` is the top-level **Scope** object for a given file. @root = @parent?.root ? this Adds a new variable or overrides an existing one. add: (name, type, immediate) -> return @parent.add name, type, immediate if @shared and not immediate if Object::hasOwnProperty.call @positions, name @variables[@positions[name]].type = type else @positions[name] = @variables.push({name, type}) - 1 When `super` is called, we need to find the name of the current method we're in, so that we know how to invoke the same method of the parent class. This can get complicated if super is being called from an inner function. `namedMethod` will walk up the scope tree until it either finds the first function object that has a name filled in, or bottoms out. namedMethod: -> return @method if @method?.name or !@parent @parent.namedMethod() Look up a variable name in lexical scope, and declare it if it does not already exist. find: (name) -> return yes if @check name @add name, 'var' no Reserve a variable name as originating from a function parameter for this scope. No `var` required for internal references. parameter: (name) -> return if @shared and @parent.check name, yes @add name, 'param' Just check to see if a variable has already been declared, without reserving, walks up to the root scope. check: (name) -> !!(@type(name) or @parent?.check(name)) Generate a temporary variable name at the given index. temporary: (name, index, single=false) -> if single (index + parseInt name, 36).toString(36).replace /\d/g, 'a' else name + (index or '') Gets the type of a variable. type: (name) -> return v.type for v in @variables when v.name is name null If we need to store an intermediate result, find an available name for a compiler-generated variable. `_var`, `_var2`, and so on... freeVariable: (name, options={}) -> index = 0 loop temp = @temporary name, index, options.single break unless @check(temp) or temp in @root.referencedVars index++ @add temp, 'var', yes if options.reserve ? true temp Ensure that an assignment is made at the top of this scope (or at the top-level scope, if requested). assign: (name, value) -> @add name, {value, assigned: yes}, yes @hasAssignments = yes Does this scope have any declared variables? hasDeclarations: -> !!@declaredVariables().length Return the list of variables first declared in this scope. declaredVariables: -> (v.name for v in @variables when v.type is 'var').sort() Return the list of assignments that are supposed to be made at the top of this scope. assignedVariables: -> "#{v.name} = #{v.type.value}" for v in @variables when v.type.assigned 1.9.3~dfsg/src/sourcemap.litcoffee0000644000000000000000000001411012531364553015741 0ustar rootrootSource maps allow JavaScript runtimes to match running JavaScript back to the original source code that corresponds to it. This can be minified JavaScript, but in our case, we're concerned with mapping pretty-printed JavaScript back to CoffeeScript. In order to produce maps, we must keep track of positions (line number, column number) that originated every node in the syntax tree, and be able to generate a [map file](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit) — which is a compact, VLQ-encoded representation of the JSON serialization of this information — to write out alongside the generated JavaScript. LineMap ------- A **LineMap** object keeps track of information about original line and column positions for a single line of output JavaScript code. **SourceMaps** are implemented in terms of **LineMaps**. class LineMap constructor: (@line) -> @columns = [] add: (column, [sourceLine, sourceColumn], options={}) -> return if @columns[column] and options.noReplace @columns[column] = {line: @line, column, sourceLine, sourceColumn} sourceLocation: (column) -> column-- until (mapping = @columns[column]) or (column <= 0) mapping and [mapping.sourceLine, mapping.sourceColumn] SourceMap --------- Maps locations in a single generated JavaScript file back to locations in the original CoffeeScript source file. This is intentionally agnostic towards how a source map might be represented on disk. Once the compiler is ready to produce a "v3"-style source map, we can walk through the arrays of line and column buffer to produce it. class SourceMap constructor: -> @lines = [] Adds a mapping to this SourceMap. `sourceLocation` and `generatedLocation` are both `[line, column]` arrays. If `options.noReplace` is true, then if there is already a mapping for the specified `line` and `column`, this will have no effect. add: (sourceLocation, generatedLocation, options = {}) -> [line, column] = generatedLocation lineMap = (@lines[line] or= new LineMap(line)) lineMap.add column, sourceLocation, options Look up the original position of a given `line` and `column` in the generated code. sourceLocation: ([line, column]) -> line-- until (lineMap = @lines[line]) or (line <= 0) lineMap and lineMap.sourceLocation column V3 SourceMap Generation ----------------------- Builds up a V3 source map, returning the generated JSON as a string. `options.sourceRoot` may be used to specify the sourceRoot written to the source map. Also, `options.sourceFiles` and `options.generatedFile` may be passed to set "sources" and "file", respectively. generate: (options = {}, code = null) -> writingline = 0 lastColumn = 0 lastSourceLine = 0 lastSourceColumn = 0 needComma = no buffer = "" for lineMap, lineNumber in @lines when lineMap for mapping in lineMap.columns when mapping while writingline < mapping.line lastColumn = 0 needComma = no buffer += ";" writingline++ Write a comma if we've already written a segment on this line. if needComma buffer += "," needComma = no Write the next segment. Segments can be 1, 4, or 5 values. If just one, then it is a generated column which doesn't match anything in the source code. The starting column in the generated source, relative to any previous recorded column for the current line: buffer += @encodeVlq mapping.column - lastColumn lastColumn = mapping.column The index into the list of sources: buffer += @encodeVlq 0 The starting line in the original source, relative to the previous source line. buffer += @encodeVlq mapping.sourceLine - lastSourceLine lastSourceLine = mapping.sourceLine The starting column in the original source, relative to the previous column. buffer += @encodeVlq mapping.sourceColumn - lastSourceColumn lastSourceColumn = mapping.sourceColumn needComma = yes Produce the canonical JSON object format for a "v3" source map. v3 = version: 3 file: options.generatedFile or '' sourceRoot: options.sourceRoot or '' sources: options.sourceFiles or [''] names: [] mappings: buffer v3.sourcesContent = [code] if options.inline JSON.stringify v3, null, 2 Base64 VLQ Encoding ------------------- Note that SourceMap VLQ encoding is "backwards". MIDI-style VLQ encoding puts the most-significant-bit (MSB) from the original value into the MSB of the VLQ encoded value (see [Wikipedia](http://en.wikipedia.org/wiki/File:Uintvar_coding.svg)). SourceMap VLQ does things the other way around, with the least significat four bits of the original value encoded into the first byte of the VLQ encoded value. VLQ_SHIFT = 5 VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT # 0010 0000 VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - 1 # 0001 1111 encodeVlq: (value) -> answer = '' # Least significant bit represents the sign. signBit = if value < 0 then 1 else 0 # The next bits are the actual value. valueToEncode = (Math.abs(value) << 1) + signBit # Make sure we encode at least one character, even if valueToEncode is 0. while valueToEncode or not answer nextChunk = valueToEncode & VLQ_VALUE_MASK valueToEncode = valueToEncode >> VLQ_SHIFT nextChunk |= VLQ_CONTINUATION_BIT if valueToEncode answer += @encodeBase64 nextChunk answer Regular Base64 Encoding ----------------------- BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' encodeBase64: (value) -> BASE64_CHARS[value] or throw new Error "Cannot Base64 encode value: #{value}" Our API for source maps is just the `SourceMap` class. module.exports = SourceMap 1.9.3~dfsg/src/grammar.coffee0000644000000000000000000006136412531364553014675 0ustar rootroot# The CoffeeScript parser is generated by [Jison](http://github.com/zaach/jison) # from this grammar file. Jison is a bottom-up parser generator, similar in # style to [Bison](http://www.gnu.org/software/bison), implemented in JavaScript. # It can recognize [LALR(1), LR(0), SLR(1), and LR(1)](http://en.wikipedia.org/wiki/LR_grammar) # type grammars. To create the Jison parser, we list the pattern to match # on the left-hand side, and the action to take (usually the creation of syntax # tree nodes) on the right. As the parser runs, it # shifts tokens from our token stream, from left to right, and # [attempts to match](http://en.wikipedia.org/wiki/Bottom-up_parsing) # the token sequence against the rules below. When a match can be made, it # reduces into the [nonterminal](http://en.wikipedia.org/wiki/Terminal_and_nonterminal_symbols) # (the enclosing name at the top), and we proceed from there. # # If you run the `cake build:parser` command, Jison constructs a parse table # from our rules and saves it into `lib/parser.js`. # The only dependency is on the **Jison.Parser**. {Parser} = require 'jison' # Jison DSL # --------- # Since we're going to be wrapped in a function by Jison in any case, if our # action immediately returns a value, we can optimize by removing the function # wrapper and just returning the value directly. unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/ # Our handy DSL for Jison grammar generation, thanks to # [Tim Caswell](http://github.com/creationix). For every rule in the grammar, # we pass the pattern-defining string, the action to run, and extra options, # optionally. If no action is specified, we simply pass the value of the # previous nonterminal. o = (patternString, action, options) -> patternString = patternString.replace /\s{2,}/g, ' ' patternCount = patternString.split(' ').length return [patternString, '$$ = $1;', options] unless action action = if match = unwrap.exec action then match[1] else "(#{action}())" # All runtime functions we need are defined on "yy" action = action.replace /\bnew /g, '$&yy.' action = action.replace /\b(?:Block\.wrap|extend)\b/g, 'yy.$&' # Returns a function which adds location data to the first parameter passed # in, and returns the parameter. If the parameter is not a node, it will # just be passed through unaffected. addLocationDataFn = (first, last) -> if not last "yy.addLocationDataFn(@#{first})" else "yy.addLocationDataFn(@#{first}, @#{last})" action = action.replace /LOC\(([0-9]*)\)/g, addLocationDataFn('$1') action = action.replace /LOC\(([0-9]*),\s*([0-9]*)\)/g, addLocationDataFn('$1', '$2') [patternString, "$$ = #{addLocationDataFn(1, patternCount)}(#{action});", options] # Grammatical Rules # ----------------- # In all of the rules that follow, you'll see the name of the nonterminal as # the key to a list of alternative matches. With each match's action, the # dollar-sign variables are provided by Jison as references to the value of # their numeric position, so in this rule: # # "Expression UNLESS Expression" # # `$1` would be the value of the first `Expression`, `$2` would be the token # for the `UNLESS` terminal, and `$3` would be the value of the second # `Expression`. grammar = # The **Root** is the top-level node in the syntax tree. Since we parse bottom-up, # all parsing must end here. Root: [ o '', -> new Block o 'Body' ] # Any list of statements and expressions, separated by line breaks or semicolons. Body: [ o 'Line', -> Block.wrap [$1] o 'Body TERMINATOR Line', -> $1.push $3 o 'Body TERMINATOR' ] # Block and statements, which make up a line in a body. Line: [ o 'Expression' o 'Statement' ] # Pure statements which cannot be expressions. Statement: [ o 'Return' o 'Comment' o 'STATEMENT', -> new Literal $1 ] # All the different types of expressions in our language. The basic unit of # CoffeeScript is the **Expression** -- everything that can be an expression # is one. Blocks serve as the building blocks of many other rules, making # them somewhat circular. Expression: [ o 'Value' o 'Invocation' o 'Code' o 'Operation' o 'Assign' o 'If' o 'Try' o 'While' o 'For' o 'Switch' o 'Class' o 'Throw' ] # An indented block of expressions. Note that the [Rewriter](rewriter.html) # will convert some postfix forms into blocks for us, by adjusting the # token stream. Block: [ o 'INDENT OUTDENT', -> new Block o 'INDENT Body OUTDENT', -> $2 ] # A literal identifier, a variable name or property. Identifier: [ o 'IDENTIFIER', -> new Literal $1 ] # Alphanumerics are separated from the other **Literal** matchers because # they can also serve as keys in object literals. AlphaNumeric: [ o 'NUMBER', -> new Literal $1 o 'String' ] String: [ o 'STRING', -> new Literal $1 o 'STRING_START Body STRING_END', -> new Parens $2 ] Regex: [ o 'REGEX', -> new Literal $1 o 'REGEX_START Invocation REGEX_END', -> $2 ] # All of our immediate values. Generally these can be passed straight # through and printed to JavaScript. Literal: [ o 'AlphaNumeric' o 'JS', -> new Literal $1 o 'Regex' o 'DEBUGGER', -> new Literal $1 o 'UNDEFINED', -> new Undefined o 'NULL', -> new Null o 'BOOL', -> new Bool $1 ] # Assignment of a variable, property, or index to a value. Assign: [ o 'Assignable = Expression', -> new Assign $1, $3 o 'Assignable = TERMINATOR Expression', -> new Assign $1, $4 o 'Assignable = INDENT Expression OUTDENT', -> new Assign $1, $4 ] # Assignment when it happens within an object literal. The difference from # the ordinary **Assign** is that these allow numbers and strings as keys. AssignObj: [ o 'ObjAssignable', -> new Value $1 o 'ObjAssignable : Expression', -> new Assign LOC(1)(new Value($1)), $3, 'object' o 'ObjAssignable : INDENT Expression OUTDENT', -> new Assign LOC(1)(new Value($1)), $4, 'object' o 'Comment' ] ObjAssignable: [ o 'Identifier' o 'AlphaNumeric' o 'ThisProperty' ] # A return statement from a function body. Return: [ o 'RETURN Expression', -> new Return $2 o 'RETURN', -> new Return ] # A block comment. Comment: [ o 'HERECOMMENT', -> new Comment $1 ] # The **Code** node is the function literal. It's defined by an indented block # of **Block** preceded by a function arrow, with an optional parameter # list. Code: [ o 'PARAM_START ParamList PARAM_END FuncGlyph Block', -> new Code $2, $5, $4 o 'FuncGlyph Block', -> new Code [], $2, $1 ] # CoffeeScript has two different symbols for functions. `->` is for ordinary # functions, and `=>` is for functions bound to the current value of *this*. FuncGlyph: [ o '->', -> 'func' o '=>', -> 'boundfunc' ] # An optional, trailing comma. OptComma: [ o '' o ',' ] # The list of parameters that a function accepts can be of any length. ParamList: [ o '', -> [] o 'Param', -> [$1] o 'ParamList , Param', -> $1.concat $3 o 'ParamList OptComma TERMINATOR Param', -> $1.concat $4 o 'ParamList OptComma INDENT ParamList OptComma OUTDENT', -> $1.concat $4 ] # A single parameter in a function definition can be ordinary, or a splat # that hoovers up the remaining arguments. Param: [ o 'ParamVar', -> new Param $1 o 'ParamVar ...', -> new Param $1, null, on o 'ParamVar = Expression', -> new Param $1, $3 o '...', -> new Expansion ] # Function Parameters ParamVar: [ o 'Identifier' o 'ThisProperty' o 'Array' o 'Object' ] # A splat that occurs outside of a parameter list. Splat: [ o 'Expression ...', -> new Splat $1 ] # Variables and properties that can be assigned to. SimpleAssignable: [ o 'Identifier', -> new Value $1 o 'Value Accessor', -> $1.add $2 o 'Invocation Accessor', -> new Value $1, [].concat $2 o 'ThisProperty' ] # Everything that can be assigned to. Assignable: [ o 'SimpleAssignable' o 'Array', -> new Value $1 o 'Object', -> new Value $1 ] # The types of things that can be treated as values -- assigned to, invoked # as functions, indexed into, named as a class, etc. Value: [ o 'Assignable' o 'Literal', -> new Value $1 o 'Parenthetical', -> new Value $1 o 'Range', -> new Value $1 o 'This' ] # The general group of accessors into an object, by property, by prototype # or by array index or slice. Accessor: [ o '. Identifier', -> new Access $2 o '?. Identifier', -> new Access $2, 'soak' o ':: Identifier', -> [LOC(1)(new Access new Literal('prototype')), LOC(2)(new Access $2)] o '?:: Identifier', -> [LOC(1)(new Access new Literal('prototype'), 'soak'), LOC(2)(new Access $2)] o '::', -> new Access new Literal 'prototype' o 'Index' ] # Indexing into an object or array using bracket notation. Index: [ o 'INDEX_START IndexValue INDEX_END', -> $2 o 'INDEX_SOAK Index', -> extend $2, soak : yes ] IndexValue: [ o 'Expression', -> new Index $1 o 'Slice', -> new Slice $1 ] # In CoffeeScript, an object literal is simply a list of assignments. Object: [ o '{ AssignList OptComma }', -> new Obj $2, $1.generated ] # Assignment of properties within an object literal can be separated by # comma, as in JavaScript, or simply by newline. AssignList: [ o '', -> [] o 'AssignObj', -> [$1] o 'AssignList , AssignObj', -> $1.concat $3 o 'AssignList OptComma TERMINATOR AssignObj', -> $1.concat $4 o 'AssignList OptComma INDENT AssignList OptComma OUTDENT', -> $1.concat $4 ] # Class definitions have optional bodies of prototype property assignments, # and optional references to the superclass. Class: [ o 'CLASS', -> new Class o 'CLASS Block', -> new Class null, null, $2 o 'CLASS EXTENDS Expression', -> new Class null, $3 o 'CLASS EXTENDS Expression Block', -> new Class null, $3, $4 o 'CLASS SimpleAssignable', -> new Class $2 o 'CLASS SimpleAssignable Block', -> new Class $2, null, $3 o 'CLASS SimpleAssignable EXTENDS Expression', -> new Class $2, $4 o 'CLASS SimpleAssignable EXTENDS Expression Block', -> new Class $2, $4, $5 ] # Ordinary function invocation, or a chained series of calls. Invocation: [ o 'Value OptFuncExist Arguments', -> new Call $1, $3, $2 o 'Invocation OptFuncExist Arguments', -> new Call $1, $3, $2 o 'SUPER', -> new Call 'super', [new Splat new Literal 'arguments'] o 'SUPER Arguments', -> new Call 'super', $2 ] # An optional existence check on a function. OptFuncExist: [ o '', -> no o 'FUNC_EXIST', -> yes ] # The list of arguments to a function call. Arguments: [ o 'CALL_START CALL_END', -> [] o 'CALL_START ArgList OptComma CALL_END', -> $2 ] # A reference to the *this* current object. This: [ o 'THIS', -> new Value new Literal 'this' o '@', -> new Value new Literal 'this' ] # A reference to a property on *this*. ThisProperty: [ o '@ Identifier', -> new Value LOC(1)(new Literal('this')), [LOC(2)(new Access($2))], 'this' ] # The array literal. Array: [ o '[ ]', -> new Arr [] o '[ ArgList OptComma ]', -> new Arr $2 ] # Inclusive and exclusive range dots. RangeDots: [ o '..', -> 'inclusive' o '...', -> 'exclusive' ] # The CoffeeScript range literal. Range: [ o '[ Expression RangeDots Expression ]', -> new Range $2, $4, $3 ] # Array slice literals. Slice: [ o 'Expression RangeDots Expression', -> new Range $1, $3, $2 o 'Expression RangeDots', -> new Range $1, null, $2 o 'RangeDots Expression', -> new Range null, $2, $1 o 'RangeDots', -> new Range null, null, $1 ] # The **ArgList** is both the list of objects passed into a function call, # as well as the contents of an array literal # (i.e. comma-separated expressions). Newlines work as well. ArgList: [ o 'Arg', -> [$1] o 'ArgList , Arg', -> $1.concat $3 o 'ArgList OptComma TERMINATOR Arg', -> $1.concat $4 o 'INDENT ArgList OptComma OUTDENT', -> $2 o 'ArgList OptComma INDENT ArgList OptComma OUTDENT', -> $1.concat $4 ] # Valid arguments are Blocks or Splats. Arg: [ o 'Expression' o 'Splat' o '...', -> new Expansion ] # Just simple, comma-separated, required arguments (no fancy syntax). We need # this to be separate from the **ArgList** for use in **Switch** blocks, where # having the newlines wouldn't make sense. SimpleArgs: [ o 'Expression' o 'SimpleArgs , Expression', -> [].concat $1, $3 ] # The variants of *try/catch/finally* exception handling blocks. Try: [ o 'TRY Block', -> new Try $2 o 'TRY Block Catch', -> new Try $2, $3[0], $3[1] o 'TRY Block FINALLY Block', -> new Try $2, null, null, $4 o 'TRY Block Catch FINALLY Block', -> new Try $2, $3[0], $3[1], $5 ] # A catch clause names its error and runs a block of code. Catch: [ o 'CATCH Identifier Block', -> [$2, $3] o 'CATCH Object Block', -> [LOC(2)(new Value($2)), $3] o 'CATCH Block', -> [null, $2] ] # Throw an exception object. Throw: [ o 'THROW Expression', -> new Throw $2 ] # Parenthetical expressions. Note that the **Parenthetical** is a **Value**, # not an **Expression**, so if you need to use an expression in a place # where only values are accepted, wrapping it in parentheses will always do # the trick. Parenthetical: [ o '( Body )', -> new Parens $2 o '( INDENT Body OUTDENT )', -> new Parens $3 ] # The condition portion of a while loop. WhileSource: [ o 'WHILE Expression', -> new While $2 o 'WHILE Expression WHEN Expression', -> new While $2, guard: $4 o 'UNTIL Expression', -> new While $2, invert: true o 'UNTIL Expression WHEN Expression', -> new While $2, invert: true, guard: $4 ] # The while loop can either be normal, with a block of expressions to execute, # or postfix, with a single expression. There is no do..while. While: [ o 'WhileSource Block', -> $1.addBody $2 o 'Statement WhileSource', -> $2.addBody LOC(1) Block.wrap([$1]) o 'Expression WhileSource', -> $2.addBody LOC(1) Block.wrap([$1]) o 'Loop', -> $1 ] Loop: [ o 'LOOP Block', -> new While(LOC(1) new Literal 'true').addBody $2 o 'LOOP Expression', -> new While(LOC(1) new Literal 'true').addBody LOC(2) Block.wrap [$2] ] # Array, object, and range comprehensions, at the most generic level. # Comprehensions can either be normal, with a block of expressions to execute, # or postfix, with a single expression. For: [ o 'Statement ForBody', -> new For $1, $2 o 'Expression ForBody', -> new For $1, $2 o 'ForBody Block', -> new For $2, $1 ] ForBody: [ o 'FOR Range', -> source: (LOC(2) new Value($2)) o 'FOR Range BY Expression', -> source: (LOC(2) new Value($2)), step: $4 o 'ForStart ForSource', -> $2.own = $1.own; $2.name = $1[0]; $2.index = $1[1]; $2 ] ForStart: [ o 'FOR ForVariables', -> $2 o 'FOR OWN ForVariables', -> $3.own = yes; $3 ] # An array of all accepted values for a variable inside the loop. # This enables support for pattern matching. ForValue: [ o 'Identifier' o 'ThisProperty' o 'Array', -> new Value $1 o 'Object', -> new Value $1 ] # An array or range comprehension has variables for the current element # and (optional) reference to the current index. Or, *key, value*, in the case # of object comprehensions. ForVariables: [ o 'ForValue', -> [$1] o 'ForValue , ForValue', -> [$1, $3] ] # The source of a comprehension is an array or object with an optional guard # clause. If it's an array comprehension, you can also choose to step through # in fixed-size increments. ForSource: [ o 'FORIN Expression', -> source: $2 o 'FOROF Expression', -> source: $2, object: yes o 'FORIN Expression WHEN Expression', -> source: $2, guard: $4 o 'FOROF Expression WHEN Expression', -> source: $2, guard: $4, object: yes o 'FORIN Expression BY Expression', -> source: $2, step: $4 o 'FORIN Expression WHEN Expression BY Expression', -> source: $2, guard: $4, step: $6 o 'FORIN Expression BY Expression WHEN Expression', -> source: $2, step: $4, guard: $6 ] Switch: [ o 'SWITCH Expression INDENT Whens OUTDENT', -> new Switch $2, $4 o 'SWITCH Expression INDENT Whens ELSE Block OUTDENT', -> new Switch $2, $4, $6 o 'SWITCH INDENT Whens OUTDENT', -> new Switch null, $3 o 'SWITCH INDENT Whens ELSE Block OUTDENT', -> new Switch null, $3, $5 ] Whens: [ o 'When' o 'Whens When', -> $1.concat $2 ] # An individual **When** clause, with action. When: [ o 'LEADING_WHEN SimpleArgs Block', -> [[$2, $3]] o 'LEADING_WHEN SimpleArgs Block TERMINATOR', -> [[$2, $3]] ] # The most basic form of *if* is a condition and an action. The following # if-related rules are broken up along these lines in order to avoid # ambiguity. IfBlock: [ o 'IF Expression Block', -> new If $2, $3, type: $1 o 'IfBlock ELSE IF Expression Block', -> $1.addElse LOC(3,5) new If $4, $5, type: $3 ] # The full complement of *if* expressions, including postfix one-liner # *if* and *unless*. If: [ o 'IfBlock' o 'IfBlock ELSE Block', -> $1.addElse $3 o 'Statement POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true o 'Expression POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true ] # Arithmetic and logical operators, working on one or more operands. # Here they are grouped by order of precedence. The actual precedence rules # are defined at the bottom of the page. It would be shorter if we could # combine most of these rules into a single generic *Operand OpSymbol Operand* # -type rule, but in order to make the precedence binding possible, separate # rules are necessary. Operation: [ o 'UNARY Expression', -> new Op $1 , $2 o 'UNARY_MATH Expression', -> new Op $1 , $2 o '- Expression', (-> new Op '-', $2), prec: 'UNARY_MATH' o '+ Expression', (-> new Op '+', $2), prec: 'UNARY_MATH' o 'YIELD Statement', -> new Op $1 , $2 o 'YIELD Expression', -> new Op $1 , $2 o 'YIELD FROM Expression', -> new Op $1.concat($2) , $3 o '-- SimpleAssignable', -> new Op '--', $2 o '++ SimpleAssignable', -> new Op '++', $2 o 'SimpleAssignable --', -> new Op '--', $1, null, true o 'SimpleAssignable ++', -> new Op '++', $1, null, true # [The existential operator](http://jashkenas.github.com/coffee-script/#existence). o 'Expression ?', -> new Existence $1 o 'Expression + Expression', -> new Op '+' , $1, $3 o 'Expression - Expression', -> new Op '-' , $1, $3 o 'Expression MATH Expression', -> new Op $2, $1, $3 o 'Expression ** Expression', -> new Op $2, $1, $3 o 'Expression SHIFT Expression', -> new Op $2, $1, $3 o 'Expression COMPARE Expression', -> new Op $2, $1, $3 o 'Expression LOGIC Expression', -> new Op $2, $1, $3 o 'Expression RELATION Expression', -> if $2.charAt(0) is '!' new Op($2[1..], $1, $3).invert() else new Op $2, $1, $3 o 'SimpleAssignable COMPOUND_ASSIGN Expression', -> new Assign $1, $3, $2 o 'SimpleAssignable COMPOUND_ASSIGN INDENT Expression OUTDENT', -> new Assign $1, $4, $2 o 'SimpleAssignable COMPOUND_ASSIGN TERMINATOR Expression', -> new Assign $1, $4, $2 o 'SimpleAssignable EXTENDS Expression', -> new Extends $1, $3 ] # Precedence # ---------- # Operators at the top of this list have higher precedence than the ones lower # down. Following these rules is what makes `2 + 3 * 4` parse as: # # 2 + (3 * 4) # # And not: # # (2 + 3) * 4 operators = [ ['left', '.', '?.', '::', '?::'] ['left', 'CALL_START', 'CALL_END'] ['nonassoc', '++', '--'] ['left', '?'] ['right', 'UNARY'] ['right', '**'] ['right', 'UNARY_MATH'] ['left', 'MATH'] ['left', '+', '-'] ['left', 'SHIFT'] ['left', 'RELATION'] ['left', 'COMPARE'] ['left', 'LOGIC'] ['nonassoc', 'INDENT', 'OUTDENT'] ['right', 'YIELD'] ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'] ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'] ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'] ['left', 'POST_IF'] ] # Wrapping Up # ----------- # Finally, now that we have our **grammar** and our **operators**, we can create # our **Jison.Parser**. We do this by processing all of our rules, recording all # terminals (every symbol which does not appear as the name of a rule above) # as "tokens". tokens = [] for name, alternatives of grammar grammar[name] = for alt in alternatives for token in alt[0].split ' ' tokens.push token unless grammar[token] alt[1] = "return #{alt[1]}" if name is 'Root' alt # Initialize the **Parser** with our list of terminal **tokens**, our **grammar** # rules, and the name of the root. Reverse the operators because Jison orders # precedence from low to high, and we have it high to low # (as in [Yacc](http://dinosaur.compilertools.net/yacc/index.html)). exports.parser = new Parser tokens : tokens.join ' ' bnf : grammar operators : operators.reverse() startSymbol : 'Root' 1.9.3~dfsg/src/coffee-script.coffee0000644000000000000000000002630012531364553015767 0ustar rootroot# CoffeeScript can be used both on the server, as a command-line compiler based # on Node.js/V8, or to run CoffeeScript directly in the browser. This module # contains the main entry functions for tokenizing, parsing, and compiling # source CoffeeScript into JavaScript. fs = require 'fs' vm = require 'vm' path = require 'path' {Lexer} = require './lexer' {parser} = require './parser' helpers = require './helpers' SourceMap = require './sourcemap' # The current CoffeeScript version number. exports.VERSION = '1.9.3' exports.FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.md'] # Expose helpers for testing. exports.helpers = helpers # Function wrapper to add source file information to SyntaxErrors thrown by the # lexer/parser/compiler. withPrettyErrors = (fn) -> (code, options = {}) -> try fn.call @, code, options catch err throw err if typeof code isnt 'string' # Support `CoffeeScript.nodes(tokens)`. throw helpers.updateSyntaxError err, code, options.filename # Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler. # # If `options.sourceMap` is specified, then `options.filename` must also be specified. All # options that can be passed to `SourceMap#generate` may also be passed here. # # This returns a javascript string, unless `options.sourceMap` is passed, # in which case this returns a `{js, v3SourceMap, sourceMap}` # object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for doing programatic # lookups. exports.compile = compile = withPrettyErrors (code, options) -> {merge, extend} = helpers options = extend {}, options if options.sourceMap map = new SourceMap tokens = lexer.tokenize code, options # Pass a list of referenced variables, so that generated variables won't get # the same name. options.referencedVars = ( token[1] for token in tokens when token.variable ) fragments = parser.parse(tokens).compileToFragments options currentLine = 0 currentLine += 1 if options.header currentLine += 1 if options.shiftLine currentColumn = 0 js = "" for fragment in fragments # Update the sourcemap with data from each fragment if options.sourceMap # Do not include empty, whitespace, or semicolon-only fragments. if fragment.locationData and not /^[;\s]*$/.test fragment.code map.add( [fragment.locationData.first_line, fragment.locationData.first_column] [currentLine, currentColumn] {noReplace: true}) newLines = helpers.count fragment.code, "\n" currentLine += newLines if newLines currentColumn = fragment.code.length - (fragment.code.lastIndexOf("\n") + 1) else currentColumn += fragment.code.length # Copy the code from each fragment into the final JavaScript. js += fragment.code if options.header header = "Generated by CoffeeScript #{@VERSION}" js = "// #{header}\n#{js}" if options.sourceMap answer = {js} answer.sourceMap = map answer.v3SourceMap = map.generate(options, code) answer else js # Tokenize a string of CoffeeScript code, and return the array of tokens. exports.tokens = withPrettyErrors (code, options) -> lexer.tokenize code, options # Parse a string of CoffeeScript code or an array of lexed tokens, and # return the AST. You can then compile it by calling `.compile()` on the root, # or traverse it by using `.traverseChildren()` with a callback. exports.nodes = withPrettyErrors (source, options) -> if typeof source is 'string' parser.parse lexer.tokenize source, options else parser.parse source # Compile and execute a string of CoffeeScript (on the server), correctly # setting `__filename`, `__dirname`, and relative `require()`. exports.run = (code, options = {}) -> mainModule = require.main # Set the filename. mainModule.filename = process.argv[1] = if options.filename then fs.realpathSync(options.filename) else '.' # Clear the module cache. mainModule.moduleCache and= {} # Assign paths for node_modules loading dir = if options.filename path.dirname fs.realpathSync options.filename else fs.realpathSync '.' mainModule.paths = require('module')._nodeModulePaths dir # Compile. if not helpers.isCoffee(mainModule.filename) or require.extensions answer = compile code, options code = answer.js ? answer mainModule._compile code, mainModule.filename # Compile and evaluate a string of CoffeeScript (in a Node.js-like environment). # The CoffeeScript REPL uses this to run the input. exports.eval = (code, options = {}) -> return unless code = code.trim() createContext = vm.Script.createContext ? vm.createContext isContext = vm.isContext ? (ctx) -> options.sandbox instanceof createContext().constructor if createContext if options.sandbox? if isContext options.sandbox sandbox = options.sandbox else sandbox = createContext() sandbox[k] = v for own k, v of options.sandbox sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox else sandbox = global sandbox.__filename = options.filename || 'eval' sandbox.__dirname = path.dirname sandbox.__filename # define module/require only if they chose not to specify their own unless sandbox isnt global or sandbox.module or sandbox.require Module = require 'module' sandbox.module = _module = new Module(options.modulename || 'eval') sandbox.require = _require = (path) -> Module._load path, _module, true _module.filename = sandbox.__filename _require[r] = require[r] for r in Object.getOwnPropertyNames require when r isnt 'paths' # use the same hack node currently uses for their own REPL _require.paths = _module.paths = Module._nodeModulePaths process.cwd() _require.resolve = (request) -> Module._resolveFilename request, _module o = {} o[k] = v for own k, v of options o.bare = on # ensure return value js = compile code, o if sandbox is global vm.runInThisContext js else vm.runInContext js, sandbox exports.register = -> require './register' # Throw error with deprecation warning when depending upon implicit `require.extensions` registration if require.extensions for ext in @FILE_EXTENSIONS require.extensions[ext] ?= -> throw new Error """ Use CoffeeScript.register() or require the coffee-script/register module to require #{ext} files. """ exports._compileFile = (filename, sourceMap = no) -> raw = fs.readFileSync filename, 'utf8' stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw try answer = compile(stripped, {filename, sourceMap, literate: helpers.isLiterate filename}) catch err # As the filename and code of a dynamically loaded file will be different # from the original file compiled with CoffeeScript.run, add that # information to error so it can be pretty-printed later. throw helpers.updateSyntaxError err, stripped, filename answer # Instantiate a Lexer for our use here. lexer = new Lexer # The real Lexer produces a generic stream of tokens. This object provides a # thin wrapper around it, compatible with the Jison API. We can then pass it # directly as a "Jison lexer". parser.lexer = lex: -> token = parser.tokens[@pos++] if token [tag, @yytext, @yylloc] = token parser.errorToken = token.origin or token @yylineno = @yylloc.first_line else tag = '' tag setInput: (tokens) -> parser.tokens = tokens @pos = 0 upcomingInput: -> "" # Make all the AST nodes visible to the parser. parser.yy = require './nodes' # Override Jison's default error handling function. parser.yy.parseError = (message, {token}) -> # Disregard Jison's message, it contains redundant line numer information. # Disregard the token, we take its value directly from the lexer in case # the error is caused by a generated token which might refer to its origin. {errorToken, tokens} = parser [errorTag, errorText, errorLoc] = errorToken errorText = switch when errorToken is tokens[tokens.length - 1] 'end of input' when errorTag in ['INDENT', 'OUTDENT'] 'indentation' when errorTag in ['IDENTIFIER', 'NUMBER', 'STRING', 'STRING_START', 'REGEX', 'REGEX_START'] errorTag.replace(/_START$/, '').toLowerCase() else helpers.nameWhitespaceCharacter errorText # The second argument has a `loc` property, which should have the location # data for this token. Unfortunately, Jison seems to send an outdated `loc` # (from the previous token), so we take the location information directly # from the lexer. helpers.throwSyntaxError "unexpected #{errorText}", errorLoc # Based on http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js # Modified to handle sourceMap formatSourcePosition = (frame, getSourceMapping) -> fileName = undefined fileLocation = '' if frame.isNative() fileLocation = "native" else if frame.isEval() fileName = frame.getScriptNameOrSourceURL() fileLocation = "#{frame.getEvalOrigin()}, " unless fileName else fileName = frame.getFileName() fileName or= "" line = frame.getLineNumber() column = frame.getColumnNumber() # Check for a sourceMap position source = getSourceMapping fileName, line, column fileLocation = if source "#{fileName}:#{source[0]}:#{source[1]}" else "#{fileName}:#{line}:#{column}" functionName = frame.getFunctionName() isConstructor = frame.isConstructor() isMethodCall = not (frame.isToplevel() or isConstructor) if isMethodCall methodName = frame.getMethodName() typeName = frame.getTypeName() if functionName tp = as = '' if typeName and functionName.indexOf typeName tp = "#{typeName}." if methodName and functionName.indexOf(".#{methodName}") isnt functionName.length - methodName.length - 1 as = " [as #{methodName}]" "#{tp}#{functionName}#{as} (#{fileLocation})" else "#{typeName}.#{methodName or ''} (#{fileLocation})" else if isConstructor "new #{functionName or ''} (#{fileLocation})" else if functionName "#{functionName} (#{fileLocation})" else fileLocation # Map of filenames -> sourceMap object. sourceMaps = {} # Generates the source map for a coffee file and stores it in the local cache variable. getSourceMap = (filename) -> return sourceMaps[filename] if sourceMaps[filename] return unless path?.extname(filename) in exports.FILE_EXTENSIONS answer = exports._compileFile filename, true sourceMaps[filename] = answer.sourceMap # Based on [michaelficarra/CoffeeScriptRedux](http://goo.gl/ZTx1p) # NodeJS / V8 have no support for transforming positions in stack traces using # sourceMap, so we must monkey-patch Error to display CoffeeScript source # positions. Error.prepareStackTrace = (err, stack) -> getSourceMapping = (filename, line, column) -> sourceMap = getSourceMap filename answer = sourceMap.sourceLocation [line - 1, column - 1] if sourceMap if answer then [answer[0] + 1, answer[1] + 1] else null frames = for frame in stack break if frame.getFunction() is exports.run " at #{formatSourcePosition frame, getSourceMapping}" "#{err.toString()}\n#{frames.join '\n'}\n" 1.9.3~dfsg/src/browser.coffee0000644000000000000000000000617012531364553014724 0ustar rootroot# This **Browser** compatibility layer extends core CoffeeScript functions # to make things work smoothly when compiling code directly in the browser. # We add support for loading remote Coffee scripts via **XHR**, and # `text/coffeescript` script tags, source maps via data-URLs, and so on. CoffeeScript = require './coffee-script' CoffeeScript.require = require compile = CoffeeScript.compile # Use standard JavaScript `eval` to eval code. CoffeeScript.eval = (code, options = {}) -> options.bare ?= on eval compile code, options # Running code does not provide access to this scope. CoffeeScript.run = (code, options = {}) -> options.bare = on options.shiftLine = on Function(compile code, options)() # If we're not in a browser environment, we're finished with the public API. return unless window? # Include source maps where possible. If we've got a base64 encoder, a # JSON serializer, and tools for escaping unicode characters, we're good to go. # Ported from https://developer.mozilla.org/en-US/docs/DOM/window.btoa if btoa? and JSON? and unescape? and encodeURIComponent? compile = (code, options = {}) -> options.sourceMap = true options.inline = true {js, v3SourceMap} = CoffeeScript.compile code, options "#{js}\n//# sourceMappingURL=data:application/json;base64,#{btoa unescape encodeURIComponent v3SourceMap}\n//# sourceURL=coffeescript" # Load a remote script from the current domain via XHR. CoffeeScript.load = (url, callback, options = {}, hold = false) -> options.sourceFiles = [url] xhr = if window.ActiveXObject new window.ActiveXObject('Microsoft.XMLHTTP') else new window.XMLHttpRequest() xhr.open 'GET', url, true xhr.overrideMimeType 'text/plain' if 'overrideMimeType' of xhr xhr.onreadystatechange = -> if xhr.readyState is 4 if xhr.status in [0, 200] param = [xhr.responseText, options] CoffeeScript.run param... unless hold else throw new Error "Could not load #{url}" callback param if callback xhr.send null # Activate CoffeeScript in the browser by having it compile and evaluate # all script tags with a content-type of `text/coffeescript`. # This happens on page load. runScripts = -> scripts = window.document.getElementsByTagName 'script' coffeetypes = ['text/coffeescript', 'text/literate-coffeescript'] coffees = (s for s in scripts when s.type in coffeetypes) index = 0 execute = -> param = coffees[index] if param instanceof Array CoffeeScript.run param... index++ execute() for script, i in coffees do (script, i) -> options = literate: script.type is coffeetypes[1] source = script.src or script.getAttribute('data-src') if source CoffeeScript.load source, (param) -> coffees[i] = param execute() options true else options.sourceFiles = ['embedded'] coffees[i] = [script.innerHTML, options] execute() # Listen for window load, both in decent browsers and in IE. if window.addEventListener window.addEventListener 'DOMContentLoaded', runScripts, no else window.attachEvent 'onload', runScripts 1.9.3~dfsg/src/register.coffee0000644000000000000000000000341512531364553015064 0ustar rootrootCoffeeScript = require './coffee-script' child_process = require 'child_process' helpers = require './helpers' path = require 'path' # Load and run a CoffeeScript file for Node, stripping any `BOM`s. loadFile = (module, filename) -> answer = CoffeeScript._compileFile filename, false module._compile answer, filename # If the installed version of Node supports `require.extensions`, register # CoffeeScript as an extension. if require.extensions for ext in CoffeeScript.FILE_EXTENSIONS require.extensions[ext] = loadFile # Patch Node's module loader to be able to handle multi-dot extensions. # This is a horrible thing that should not be required. Module = require 'module' findExtension = (filename) -> extensions = path.basename(filename).split '.' # Remove the initial dot from dotfiles. extensions.shift() if extensions[0] is '' # Start with the longest possible extension and work our way shortwards. while extensions.shift() curExtension = '.' + extensions.join '.' return curExtension if Module._extensions[curExtension] '.js' Module::load = (filename) -> @filename = filename @paths = Module._nodeModulePaths path.dirname filename extension = findExtension filename Module._extensions[extension](this, filename) @loaded = true # If we're on Node, patch `child_process.fork` so that Coffee scripts are able # to fork both CoffeeScript files, and JavaScript files, directly. if child_process {fork} = child_process binary = require.resolve '../../bin/coffee' child_process.fork = (path, args, options) -> if helpers.isCoffee path unless Array.isArray args options = args or {} args = [] args = [path].concat args path = binary fork path, args, options 1.9.3~dfsg/src/index.coffee0000644000000000000000000000015512531364553014345 0ustar rootroot# Loader for CoffeeScript as a Node.js library. exports[key] = val for key, val of require './coffee-script' 1.9.3~dfsg/src/helpers.coffee0000644000000000000000000001513312531364553014702 0ustar rootroot# This file contains the common helper functions that we'd like to share among # the **Lexer**, **Rewriter**, and the **Nodes**. Merge objects, flatten # arrays, count characters, that sort of thing. # Peek at the beginning of a given string to see if it matches a sequence. exports.starts = (string, literal, start) -> literal is string.substr start, literal.length # Peek at the end of a given string to see if it matches a sequence. exports.ends = (string, literal, back) -> len = literal.length literal is string.substr string.length - len - (back or 0), len # Repeat a string `n` times. exports.repeat = repeat = (str, n) -> # Use clever algorithm to have O(log(n)) string concatenation operations. res = '' while n > 0 res += str if n & 1 n >>>= 1 str += str res # Trim out all falsy values from an array. exports.compact = (array) -> item for item in array when item # Count the number of occurrences of a string in a string. exports.count = (string, substr) -> num = pos = 0 return 1/0 unless substr.length num++ while pos = 1 + string.indexOf substr, pos num # Merge objects, returning a fresh copy with attributes from both sides. # Used every time `Base#compile` is called, to allow properties in the # options hash to propagate down the tree without polluting other branches. exports.merge = (options, overrides) -> extend (extend {}, options), overrides # Extend a source object with the properties of another object (shallow copy). extend = exports.extend = (object, properties) -> for key, val of properties object[key] = val object # Return a flattened version of an array. # Handy for getting a list of `children` from the nodes. exports.flatten = flatten = (array) -> flattened = [] for element in array if element instanceof Array flattened = flattened.concat flatten element else flattened.push element flattened # Delete a key from an object, returning the value. Useful when a node is # looking for a particular method in an options hash. exports.del = (obj, key) -> val = obj[key] delete obj[key] val # Typical Array::some exports.some = Array::some ? (fn) -> return true for e in this when fn e false # Simple function for inverting Literate CoffeeScript code by putting the # documentation in comments, producing a string of CoffeeScript code that # can be compiled "normally". exports.invertLiterate = (code) -> maybe_code = true lines = for line in code.split('\n') if maybe_code and /^([ ]{4}|[ ]{0,3}\t)/.test line line else if maybe_code = /^\s*$/.test line line else '# ' + line lines.join '\n' # Merge two jison-style location data objects together. # If `last` is not provided, this will simply return `first`. buildLocationData = (first, last) -> if not last first else first_line: first.first_line first_column: first.first_column last_line: last.last_line last_column: last.last_column # This returns a function which takes an object as a parameter, and if that # object is an AST node, updates that object's locationData. # The object is returned either way. exports.addLocationDataFn = (first, last) -> (obj) -> if ((typeof obj) is 'object') and (!!obj['updateLocationDataIfMissing']) obj.updateLocationDataIfMissing buildLocationData(first, last) return obj # Convert jison location data to a string. # `obj` can be a token, or a locationData. exports.locationDataToString = (obj) -> if ("2" of obj) and ("first_line" of obj[2]) then locationData = obj[2] else if "first_line" of obj then locationData = obj if locationData "#{locationData.first_line + 1}:#{locationData.first_column + 1}-" + "#{locationData.last_line + 1}:#{locationData.last_column + 1}" else "No location data" # A `.coffee.md` compatible version of `basename`, that returns the file sans-extension. exports.baseFileName = (file, stripExt = no, useWinPathSep = no) -> pathSep = if useWinPathSep then /\\|\// else /\// parts = file.split(pathSep) file = parts[parts.length - 1] return file unless stripExt and file.indexOf('.') >= 0 parts = file.split('.') parts.pop() parts.pop() if parts[parts.length - 1] is 'coffee' and parts.length > 1 parts.join('.') # Determine if a filename represents a CoffeeScript file. exports.isCoffee = (file) -> /\.((lit)?coffee|coffee\.md)$/.test file # Determine if a filename represents a Literate CoffeeScript file. exports.isLiterate = (file) -> /\.(litcoffee|coffee\.md)$/.test file # Throws a SyntaxError from a given location. # The error's `toString` will return an error message following the "standard" # format ::: plus the line with the error and a # marker showing where the error is. exports.throwSyntaxError = (message, location) -> error = new SyntaxError message error.location = location error.toString = syntaxErrorToString # Instead of showing the compiler's stacktrace, show our custom error message # (this is useful when the error bubbles up in Node.js applications that # compile CoffeeScript for example). error.stack = error.toString() throw error # Update a compiler SyntaxError with source code information if it didn't have # it already. exports.updateSyntaxError = (error, code, filename) -> # Avoid screwing up the `stack` property of other errors (i.e. possible bugs). if error.toString is syntaxErrorToString error.code or= code error.filename or= filename error.stack = error.toString() error syntaxErrorToString = -> return Error::toString.call @ unless @code and @location {first_line, first_column, last_line, last_column} = @location last_line ?= first_line last_column ?= first_column filename = @filename or '[stdin]' codeLine = @code.split('\n')[first_line] start = first_column # Show only the first line on multi-line errors. end = if first_line is last_line then last_column + 1 else codeLine.length marker = codeLine[...start].replace(/[^\s]/g, ' ') + repeat('^', end - start) # Check to see if we're running on a color-enabled TTY. if process? colorsEnabled = process.stdout?.isTTY and not process.env?.NODE_DISABLE_COLORS if @colorful ? colorsEnabled colorize = (str) -> "\x1B[1;31m#{str}\x1B[0m" codeLine = codeLine[...start] + colorize(codeLine[start...end]) + codeLine[end..] marker = colorize marker """ #{filename}:#{first_line + 1}:#{first_column + 1}: error: #{@message} #{codeLine} #{marker} """ exports.nameWhitespaceCharacter = (string) -> switch string when ' ' then 'space' when '\n' then 'newline' when '\r' then 'carriage return' when '\t' then 'tab' else string 1.9.3~dfsg/src/cake.coffee0000644000000000000000000000670712531364553014152 0ustar rootroot# `cake` is a simplified version of [Make](http://www.gnu.org/software/make/) # ([Rake](http://rake.rubyforge.org/), [Jake](http://github.com/280north/jake)) # for CoffeeScript. You define tasks with names and descriptions in a Cakefile, # and can call them from the command line, or invoke them from other tasks. # # Running `cake` with no arguments will print out a list of all the tasks in the # current directory's Cakefile. # External dependencies. fs = require 'fs' path = require 'path' helpers = require './helpers' optparse = require './optparse' CoffeeScript = require './coffee-script' # Register .coffee extension CoffeeScript.register() # Keep track of the list of defined tasks, the accepted options, and so on. tasks = {} options = {} switches = [] oparse = null # Mixin the top-level Cake functions for Cakefiles to use directly. helpers.extend global, # Define a Cake task with a short name, an optional sentence description, # and the function to run as the action itself. task: (name, description, action) -> [action, description] = [description, action] unless action tasks[name] = {name, description, action} # Define an option that the Cakefile accepts. The parsed options hash, # containing all of the command-line options passed, will be made available # as the first argument to the action. option: (letter, flag, description) -> switches.push [letter, flag, description] # Invoke another task in the current Cakefile. invoke: (name) -> missingTask name unless tasks[name] tasks[name].action options # Run `cake`. Executes all of the tasks you pass, in order. Note that Node's # asynchrony may cause tasks to execute in a different order than you'd expect. # If no tasks are passed, print the help screen. Keep a reference to the # original directory name, when running Cake tasks from subdirectories. exports.run = -> global.__originalDirname = fs.realpathSync '.' process.chdir cakefileDirectory __originalDirname args = process.argv[2..] CoffeeScript.run fs.readFileSync('Cakefile').toString(), filename: 'Cakefile' oparse = new optparse.OptionParser switches return printTasks() unless args.length try options = oparse.parse(args) catch e return fatalError "#{e}" invoke arg for arg in options.arguments # Display the list of Cake tasks in a format similar to `rake -T` printTasks = -> relative = path.relative or path.resolve cakefilePath = path.join relative(__originalDirname, process.cwd()), 'Cakefile' console.log "#{cakefilePath} defines the following tasks:\n" for name, task of tasks spaces = 20 - name.length spaces = if spaces > 0 then Array(spaces + 1).join(' ') else '' desc = if task.description then "# #{task.description}" else '' console.log "cake #{name}#{spaces} #{desc}" console.log oparse.help() if switches.length # Print an error and exit when attempting to use an invalid task/option. fatalError = (message) -> console.error message + '\n' console.log 'To see a list of all tasks/options, run "cake"' process.exit 1 missingTask = (task) -> fatalError "No such task: #{task}" # When `cake` is invoked, search in the current and all parent directories # to find the relevant Cakefile. cakefileDirectory = (dir) -> return dir if fs.existsSync path.join dir, 'Cakefile' parent = path.normalize path.join dir, '..' return cakefileDirectory parent unless parent is dir throw new Error "Cakefile not found in #{process.cwd()}" 1.9.3~dfsg/src/nodes.coffee0000644000000000000000000024624412531364553014361 0ustar rootroot# `nodes.coffee` contains all of the node classes for the syntax tree. Most # nodes are created as the result of actions in the [grammar](grammar.html), # but some are created by other nodes as a method of code generation. To convert # the syntax tree into a string of JavaScript code, call `compile()` on the root. Error.stackTraceLimit = Infinity {Scope} = require './scope' {RESERVED, STRICT_PROSCRIBED} = require './lexer' # Import the helpers we plan to use. {compact, flatten, extend, merge, del, starts, ends, some, addLocationDataFn, locationDataToString, throwSyntaxError} = require './helpers' # Functions required by parser exports.extend = extend exports.addLocationDataFn = addLocationDataFn # Constant functions for nodes that don't need customization. YES = -> yes NO = -> no THIS = -> this NEGATE = -> @negated = not @negated; this #### CodeFragment # The various nodes defined below all compile to a collection of **CodeFragment** objects. # A CodeFragments is a block of generated code, and the location in the source file where the code # came from. CodeFragments can be assembled together into working code just by catting together # all the CodeFragments' `code` snippets, in order. exports.CodeFragment = class CodeFragment constructor: (parent, code) -> @code = "#{code}" @locationData = parent?.locationData @type = parent?.constructor?.name or 'unknown' toString: -> "#{@code}#{if @locationData then ": " + locationDataToString(@locationData) else ''}" # Convert an array of CodeFragments into a string. fragmentsToText = (fragments) -> (fragment.code for fragment in fragments).join('') #### Base # The **Base** is the abstract base class for all nodes in the syntax tree. # Each subclass implements the `compileNode` method, which performs the # code generation for that node. To compile a node to JavaScript, # call `compile` on it, which wraps `compileNode` in some generic extra smarts, # to know when the generated code needs to be wrapped up in a closure. # An options hash is passed and cloned throughout, containing information about # the environment from higher in the tree (such as if a returned value is # being requested by the surrounding function), information about the current # scope, and indentation level. exports.Base = class Base compile: (o, lvl) -> fragmentsToText @compileToFragments o, lvl # Common logic for determining whether to wrap this node in a closure before # compiling it, or to compile directly. We need to wrap if this node is a # *statement*, and it's not a *pureStatement*, and we're not at # the top level of a block (which would be unnecessary), and we haven't # already been asked to return the result (because statements know how to # return results). compileToFragments: (o, lvl) -> o = extend {}, o o.level = lvl if lvl node = @unfoldSoak(o) or this node.tab = o.indent if o.level is LEVEL_TOP or not node.isStatement(o) node.compileNode o else node.compileClosure o # Statements converted into expressions via closure-wrapping share a scope # object with their parent closure, to preserve the expected lexical scope. compileClosure: (o) -> if jumpNode = @jumps() jumpNode.error 'cannot use a pure statement in an expression' o.sharedScope = yes func = new Code [], Block.wrap [this] args = [] if (argumentsNode = @contains isLiteralArguments) or @contains isLiteralThis args = [new Literal 'this'] if argumentsNode meth = 'apply' args.push new Literal 'arguments' else meth = 'call' func = new Value func, [new Access new Literal meth] parts = (new Call func, args).compileNode o if func.isGenerator or func.base?.isGenerator parts.unshift @makeCode "(yield* " parts.push @makeCode ")" parts # If the code generation wishes to use the result of a complex expression # in multiple places, ensure that the expression is only ever evaluated once, # by assigning it to a temporary variable. Pass a level to precompile. # # If `level` is passed, then returns `[val, ref]`, where `val` is the compiled value, and `ref` # is the compiled reference. If `level` is not passed, this returns `[val, ref]` where # the two values are raw nodes which have not been compiled. cache: (o, level, isComplex) -> complex = if isComplex? then isComplex this else @isComplex() if complex ref = new Literal o.scope.freeVariable 'ref' sub = new Assign ref, this if level then [sub.compileToFragments(o, level), [@makeCode(ref.value)]] else [sub, ref] else ref = if level then @compileToFragments o, level else this [ref, ref] cacheToCodeFragments: (cacheValues) -> [fragmentsToText(cacheValues[0]), fragmentsToText(cacheValues[1])] # Construct a node that returns the current node's result. # Note that this is overridden for smarter behavior for # many statement nodes (e.g. If, For)... makeReturn: (res) -> me = @unwrapAll() if res new Call new Literal("#{res}.push"), [me] else new Return me # Does this node, or any of its children, contain a node of a certain kind? # Recursively traverses down the *children* nodes and returns the first one # that verifies `pred`. Otherwise return undefined. `contains` does not cross # scope boundaries. contains: (pred) -> node = undefined @traverseChildren no, (n) -> if pred n node = n return no node # Pull out the last non-comment node of a node list. lastNonComment: (list) -> i = list.length return list[i] while i-- when list[i] not instanceof Comment null # `toString` representation of the node, for inspecting the parse tree. # This is what `coffee --nodes` prints out. toString: (idt = '', name = @constructor.name) -> tree = '\n' + idt + name tree += '?' if @soak @eachChild (node) -> tree += node.toString idt + TAB tree # Passes each child to a function, breaking when the function returns `false`. eachChild: (func) -> return this unless @children for attr in @children when @[attr] for child in flatten [@[attr]] return this if func(child) is false this traverseChildren: (crossScope, func) -> @eachChild (child) -> recur = func(child) child.traverseChildren(crossScope, func) unless recur is no invert: -> new Op '!', this unwrapAll: -> node = this continue until node is node = node.unwrap() node # Default implementations of the common node properties and methods. Nodes # will override these with custom logic, if needed. children: [] isStatement : NO jumps : NO isComplex : YES isChainable : NO isAssignable : NO unwrap : THIS unfoldSoak : NO # Is this node used to assign a certain variable? assigns: NO # For this node and all descendents, set the location data to `locationData` # if the location data is not already set. updateLocationDataIfMissing: (locationData) -> return this if @locationData @locationData = locationData @eachChild (child) -> child.updateLocationDataIfMissing locationData # Throw a SyntaxError associated with this node's location. error: (message) -> throwSyntaxError message, @locationData makeCode: (code) -> new CodeFragment this, code wrapInBraces: (fragments) -> [].concat @makeCode('('), fragments, @makeCode(')') # `fragmentsList` is an array of arrays of fragments. Each array in fragmentsList will be # concatonated together, with `joinStr` added in between each, to produce a final flat array # of fragments. joinFragmentArrays: (fragmentsList, joinStr) -> answer = [] for fragments,i in fragmentsList if i then answer.push @makeCode joinStr answer = answer.concat fragments answer #### Block # The block is the list of expressions that forms the body of an # indented block of code -- the implementation of a function, a clause in an # `if`, `switch`, or `try`, and so on... exports.Block = class Block extends Base constructor: (nodes) -> @expressions = compact flatten nodes or [] children: ['expressions'] # Tack an expression on to the end of this expression list. push: (node) -> @expressions.push node this # Remove and return the last expression of this expression list. pop: -> @expressions.pop() # Add an expression at the beginning of this expression list. unshift: (node) -> @expressions.unshift node this # If this Block consists of just a single node, unwrap it by pulling # it back out. unwrap: -> if @expressions.length is 1 then @expressions[0] else this # Is this an empty block of code? isEmpty: -> not @expressions.length isStatement: (o) -> for exp in @expressions when exp.isStatement o return yes no jumps: (o) -> for exp in @expressions return jumpNode if jumpNode = exp.jumps o # A Block node does not return its entire body, rather it # ensures that the final expression is returned. makeReturn: (res) -> len = @expressions.length while len-- expr = @expressions[len] if expr not instanceof Comment @expressions[len] = expr.makeReturn res @expressions.splice(len, 1) if expr instanceof Return and not expr.expression break this # A **Block** is the only node that can serve as the root. compileToFragments: (o = {}, level) -> if o.scope then super o, level else @compileRoot o # Compile all expressions within the **Block** body. If we need to # return the result, and it's an expression, simply return it. If it's a # statement, ask the statement to do so. compileNode: (o) -> @tab = o.indent top = o.level is LEVEL_TOP compiledNodes = [] for node, index in @expressions node = node.unwrapAll() node = (node.unfoldSoak(o) or node) if node instanceof Block # This is a nested block. We don't do anything special here like enclose # it in a new scope; we just compile the statements in this block along with # our own compiledNodes.push node.compileNode o else if top node.front = true fragments = node.compileToFragments o unless node.isStatement o fragments.unshift @makeCode "#{@tab}" fragments.push @makeCode ";" compiledNodes.push fragments else compiledNodes.push node.compileToFragments o, LEVEL_LIST if top if @spaced return [].concat @joinFragmentArrays(compiledNodes, '\n\n'), @makeCode("\n") else return @joinFragmentArrays(compiledNodes, '\n') if compiledNodes.length answer = @joinFragmentArrays(compiledNodes, ', ') else answer = [@makeCode "void 0"] if compiledNodes.length > 1 and o.level >= LEVEL_LIST then @wrapInBraces answer else answer # If we happen to be the top-level **Block**, wrap everything in # a safety closure, unless requested not to. # It would be better not to generate them in the first place, but for now, # clean up obvious double-parentheses. compileRoot: (o) -> o.indent = if o.bare then '' else TAB o.level = LEVEL_TOP @spaced = yes o.scope = new Scope null, this, null, o.referencedVars ? [] # Mark given local variables in the root scope as parameters so they don't # end up being declared on this block. o.scope.parameter name for name in o.locals or [] prelude = [] unless o.bare preludeExps = for exp, i in @expressions break unless exp.unwrap() instanceof Comment exp rest = @expressions[preludeExps.length...] @expressions = preludeExps if preludeExps.length prelude = @compileNode merge(o, indent: '') prelude.push @makeCode "\n" @expressions = rest fragments = @compileWithDeclarations o return fragments if o.bare [].concat prelude, @makeCode("(function() {\n"), fragments, @makeCode("\n}).call(this);\n") # Compile the expressions body for the contents of a function, with # declarations of all inner variables pushed up to the top. compileWithDeclarations: (o) -> fragments = [] post = [] for exp, i in @expressions exp = exp.unwrap() break unless exp instanceof Comment or exp instanceof Literal o = merge(o, level: LEVEL_TOP) if i rest = @expressions.splice i, 9e9 [spaced, @spaced] = [@spaced, no] [fragments, @spaced] = [@compileNode(o), spaced] @expressions = rest post = @compileNode o {scope} = o if scope.expressions is this declars = o.scope.hasDeclarations() assigns = scope.hasAssignments if declars or assigns fragments.push @makeCode '\n' if i fragments.push @makeCode "#{@tab}var " if declars fragments.push @makeCode scope.declaredVariables().join(', ') if assigns fragments.push @makeCode ",\n#{@tab + TAB}" if declars fragments.push @makeCode scope.assignedVariables().join(",\n#{@tab + TAB}") fragments.push @makeCode ";\n#{if @spaced then '\n' else ''}" else if fragments.length and post.length fragments.push @makeCode "\n" fragments.concat post # Wrap up the given nodes as a **Block**, unless it already happens # to be one. @wrap: (nodes) -> return nodes[0] if nodes.length is 1 and nodes[0] instanceof Block new Block nodes #### Literal # Literals are static values that can be passed through directly into # JavaScript without translation, such as: strings, numbers, # `true`, `false`, `null`... exports.Literal = class Literal extends Base constructor: (@value) -> makeReturn: -> if @isStatement() then this else super isAssignable: -> IDENTIFIER.test @value isStatement: -> @value in ['break', 'continue', 'debugger'] isComplex: NO assigns: (name) -> name is @value jumps: (o) -> return this if @value is 'break' and not (o?.loop or o?.block) return this if @value is 'continue' and not o?.loop compileNode: (o) -> code = if @value is 'this' if o.scope.method?.bound then o.scope.method.context else @value else if @value.reserved "\"#{@value}\"" else @value answer = if @isStatement() then "#{@tab}#{code};" else code [@makeCode answer] toString: -> ' "' + @value + '"' class exports.Undefined extends Base isAssignable: NO isComplex: NO compileNode: (o) -> [@makeCode if o.level >= LEVEL_ACCESS then '(void 0)' else 'void 0'] class exports.Null extends Base isAssignable: NO isComplex: NO compileNode: -> [@makeCode "null"] class exports.Bool extends Base isAssignable: NO isComplex: NO compileNode: -> [@makeCode @val] constructor: (@val) -> #### Return # A `return` is a *pureStatement* -- wrapping it in a closure wouldn't # make sense. exports.Return = class Return extends Base constructor: (@expression) -> children: ['expression'] isStatement: YES makeReturn: THIS jumps: THIS compileToFragments: (o, level) -> expr = @expression?.makeReturn() if expr and expr not instanceof Return then expr.compileToFragments o, level else super o, level compileNode: (o) -> answer = [] exprIsYieldReturn = @expression?.isYieldReturn?() # TODO: If we call expression.compile() here twice, we'll sometimes get back different results! unless exprIsYieldReturn answer.push @makeCode @tab + "return#{if @expression then " " else ""}" if @expression answer = answer.concat @expression.compileToFragments o, LEVEL_PAREN answer.push @makeCode ";" unless exprIsYieldReturn return answer #### Value # A value, variable or literal or parenthesized, indexed or dotted into, # or vanilla. exports.Value = class Value extends Base constructor: (base, props, tag) -> return base if not props and base instanceof Value @base = base @properties = props or [] @[tag] = true if tag return this children: ['base', 'properties'] # Add a property (or *properties* ) `Access` to the list. add: (props) -> @properties = @properties.concat props this hasProperties: -> !!@properties.length bareLiteral: (type) -> not @properties.length and @base instanceof type # Some boolean checks for the benefit of other nodes. isArray : -> @bareLiteral(Arr) isRange : -> @bareLiteral(Range) isComplex : -> @hasProperties() or @base.isComplex() isAssignable : -> @hasProperties() or @base.isAssignable() isSimpleNumber : -> @bareLiteral(Literal) and SIMPLENUM.test @base.value isString : -> @bareLiteral(Literal) and IS_STRING.test @base.value isRegex : -> @bareLiteral(Literal) and IS_REGEX.test @base.value isAtomic : -> for node in @properties.concat @base return no if node.soak or node instanceof Call yes isNotCallable : -> @isSimpleNumber() or @isString() or @isRegex() or @isArray() or @isRange() or @isSplice() or @isObject() isStatement : (o) -> not @properties.length and @base.isStatement o assigns : (name) -> not @properties.length and @base.assigns name jumps : (o) -> not @properties.length and @base.jumps o isObject: (onlyGenerated) -> return no if @properties.length (@base instanceof Obj) and (not onlyGenerated or @base.generated) isSplice: -> [..., lastProp] = @properties lastProp instanceof Slice looksStatic: (className) -> @base.value is className and @properties.length is 1 and @properties[0].name?.value isnt 'prototype' # The value can be unwrapped as its inner node, if there are no attached # properties. unwrap: -> if @properties.length then this else @base # A reference has base part (`this` value) and name part. # We cache them separately for compiling complex expressions. # `a()[b()] ?= c` -> `(_base = a())[_name = b()] ? _base[_name] = c` cacheReference: (o) -> [..., name] = @properties if @properties.length < 2 and not @base.isComplex() and not name?.isComplex() return [this, this] # `a` `a.b` base = new Value @base, @properties[...-1] if base.isComplex() # `a().b` bref = new Literal o.scope.freeVariable 'base' base = new Value new Parens new Assign bref, base return [base, bref] unless name # `a()` if name.isComplex() # `a[b()]` nref = new Literal o.scope.freeVariable 'name' name = new Index new Assign nref, name.index nref = new Index nref [base.add(name), new Value(bref or base.base, [nref or name])] # We compile a value to JavaScript by compiling and joining each property. # Things get much more interesting if the chain of properties has *soak* # operators `?.` interspersed. Then we have to take care not to accidentally # evaluate anything twice when building the soak chain. compileNode: (o) -> @base.front = @front props = @properties fragments = @base.compileToFragments o, (if props.length then LEVEL_ACCESS else null) if (@base instanceof Parens or props.length) and SIMPLENUM.test fragmentsToText fragments fragments.push @makeCode '.' for prop in props fragments.push (prop.compileToFragments o)... fragments # Unfold a soak into an `If`: `a?.b` -> `a.b if a?` unfoldSoak: (o) -> @unfoldedSoak ?= do => if ifn = @base.unfoldSoak o ifn.body.properties.push @properties... return ifn for prop, i in @properties when prop.soak prop.soak = off fst = new Value @base, @properties[...i] snd = new Value @base, @properties[i..] if fst.isComplex() ref = new Literal o.scope.freeVariable 'ref' fst = new Parens new Assign ref, fst snd.base = ref return new If new Existence(fst), snd, soak: on no #### Comment # CoffeeScript passes through block comments as JavaScript block comments # at the same position. exports.Comment = class Comment extends Base constructor: (@comment) -> isStatement: YES makeReturn: THIS compileNode: (o, level) -> comment = @comment.replace /^(\s*)#(?=\s)/gm, "$1 *" code = "/*#{multident comment, @tab}#{if '\n' in comment then "\n#{@tab}" else ''} */" code = o.indent + code if (level or o.level) is LEVEL_TOP [@makeCode("\n"), @makeCode(code)] #### Call # Node for a function invocation. Takes care of converting `super()` calls into # calls against the prototype's function of the same name. exports.Call = class Call extends Base constructor: (variable, @args = [], @soak) -> @isNew = false @isSuper = variable is 'super' @variable = if @isSuper then null else variable if variable instanceof Value and variable.isNotCallable() variable.error "literal is not a function" children: ['variable', 'args'] # Tag this invocation as creating a new instance. newInstance: -> base = @variable?.base or @variable if base instanceof Call and not base.isNew base.newInstance() else @isNew = true this # Grab the reference to the superclass's implementation of the current # method. superReference: (o) -> method = o.scope.namedMethod() if method?.klass {klass, name, variable} = method if klass.isComplex() bref = new Literal o.scope.parent.freeVariable 'base' base = new Value new Parens new Assign bref, klass variable.base = base variable.properties.splice 0, klass.properties.length if name.isComplex() or (name instanceof Index and name.index.isAssignable()) nref = new Literal o.scope.parent.freeVariable 'name' name = new Index new Assign nref, name.index variable.properties.pop() variable.properties.push name accesses = [new Access new Literal '__super__'] accesses.push new Access new Literal 'constructor' if method.static accesses.push if nref? then new Index nref else name (new Value bref ? klass, accesses).compile o else if method?.ctor "#{method.name}.__super__.constructor" else @error 'cannot call super outside of an instance method.' # The appropriate `this` value for a `super` call. superThis : (o) -> method = o.scope.method (method and not method.klass and method.context) or "this" # Soaked chained invocations unfold into if/else ternary structures. unfoldSoak: (o) -> if @soak if @variable return ifn if ifn = unfoldSoak o, this, 'variable' [left, rite] = new Value(@variable).cacheReference o else left = new Literal @superReference o rite = new Value left rite = new Call rite, @args rite.isNew = @isNew left = new Literal "typeof #{ left.compile o } === \"function\"" return new If left, new Value(rite), soak: yes call = this list = [] loop if call.variable instanceof Call list.push call call = call.variable continue break unless call.variable instanceof Value list.push call break unless (call = call.variable.base) instanceof Call for call in list.reverse() if ifn if call.variable instanceof Call call.variable = ifn else call.variable.base = ifn ifn = unfoldSoak o, call, 'variable' ifn # Compile a vanilla function call. compileNode: (o) -> @variable?.front = @front compiledArray = Splat.compileSplattedArray o, @args, true if compiledArray.length return @compileSplat o, compiledArray compiledArgs = [] for arg, argIndex in @args if argIndex then compiledArgs.push @makeCode ", " compiledArgs.push (arg.compileToFragments o, LEVEL_LIST)... fragments = [] if @isSuper preface = @superReference(o) + ".call(#{@superThis(o)}" if compiledArgs.length then preface += ", " fragments.push @makeCode preface else if @isNew then fragments.push @makeCode 'new ' fragments.push @variable.compileToFragments(o, LEVEL_ACCESS)... fragments.push @makeCode "(" fragments.push compiledArgs... fragments.push @makeCode ")" fragments # If you call a function with a splat, it's converted into a JavaScript # `.apply()` call to allow an array of arguments to be passed. # If it's a constructor, then things get real tricky. We have to inject an # inner constructor in order to be able to pass the varargs. # # splatArgs is an array of CodeFragments to put into the 'apply'. compileSplat: (o, splatArgs) -> if @isSuper return [].concat @makeCode("#{ @superReference o }.apply(#{@superThis(o)}, "), splatArgs, @makeCode(")") if @isNew idt = @tab + TAB return [].concat @makeCode(""" (function(func, args, ctor) { #{idt}ctor.prototype = func.prototype; #{idt}var child = new ctor, result = func.apply(child, args); #{idt}return Object(result) === result ? result : child; #{@tab}})("""), (@variable.compileToFragments o, LEVEL_LIST), @makeCode(", "), splatArgs, @makeCode(", function(){})") answer = [] base = new Value @variable if (name = base.properties.pop()) and base.isComplex() ref = o.scope.freeVariable 'ref' answer = answer.concat @makeCode("(#{ref} = "), (base.compileToFragments o, LEVEL_LIST), @makeCode(")"), name.compileToFragments(o) else fun = base.compileToFragments o, LEVEL_ACCESS fun = @wrapInBraces fun if SIMPLENUM.test fragmentsToText fun if name ref = fragmentsToText fun fun.push (name.compileToFragments o)... else ref = 'null' answer = answer.concat fun answer = answer.concat @makeCode(".apply(#{ref}, "), splatArgs, @makeCode(")") #### Extends # Node to extend an object's prototype with an ancestor object. # After `goog.inherits` from the # [Closure Library](http://closure-library.googlecode.com/svn/docs/closureGoogBase.js.html). exports.Extends = class Extends extends Base constructor: (@child, @parent) -> children: ['child', 'parent'] # Hooks one constructor into another's prototype chain. compileToFragments: (o) -> new Call(new Value(new Literal utility 'extend', o), [@child, @parent]).compileToFragments o #### Access # A `.` access into a property of a value, or the `::` shorthand for # an access into the object's prototype. exports.Access = class Access extends Base constructor: (@name, tag) -> @name.asKey = yes @soak = tag is 'soak' children: ['name'] compileToFragments: (o) -> name = @name.compileToFragments o if IDENTIFIER.test fragmentsToText name name.unshift @makeCode "." else name.unshift @makeCode "[" name.push @makeCode "]" name isComplex: NO #### Index # A `[ ... ]` indexed access into an array or object. exports.Index = class Index extends Base constructor: (@index) -> children: ['index'] compileToFragments: (o) -> [].concat @makeCode("["), @index.compileToFragments(o, LEVEL_PAREN), @makeCode("]") isComplex: -> @index.isComplex() #### Range # A range literal. Ranges can be used to extract portions (slices) of arrays, # to specify a range for comprehensions, or as a value, to be expanded into the # corresponding array of integers at runtime. exports.Range = class Range extends Base children: ['from', 'to'] constructor: (@from, @to, tag) -> @exclusive = tag is 'exclusive' @equals = if @exclusive then '' else '=' # Compiles the range's source variables -- where it starts and where it ends. # But only if they need to be cached to avoid double evaluation. compileVariables: (o) -> o = merge o, top: true isComplex = del o, 'isComplex' [@fromC, @fromVar] = @cacheToCodeFragments @from.cache o, LEVEL_LIST, isComplex [@toC, @toVar] = @cacheToCodeFragments @to.cache o, LEVEL_LIST, isComplex [@step, @stepVar] = @cacheToCodeFragments step.cache o, LEVEL_LIST, isComplex if step = del o, 'step' [@fromNum, @toNum] = [@fromVar.match(NUMBER), @toVar.match(NUMBER)] @stepNum = @stepVar.match(NUMBER) if @stepVar # When compiled normally, the range returns the contents of the *for loop* # needed to iterate over the values in the range. Used by comprehensions. compileNode: (o) -> @compileVariables o unless @fromVar return @compileArray(o) unless o.index # Set up endpoints. known = @fromNum and @toNum idx = del o, 'index' idxName = del o, 'name' namedIndex = idxName and idxName isnt idx varPart = "#{idx} = #{@fromC}" varPart += ", #{@toC}" if @toC isnt @toVar varPart += ", #{@step}" if @step isnt @stepVar [lt, gt] = ["#{idx} <#{@equals}", "#{idx} >#{@equals}"] # Generate the condition. condPart = if @stepNum if parseNum(@stepNum[0]) > 0 then "#{lt} #{@toVar}" else "#{gt} #{@toVar}" else if known [from, to] = [parseNum(@fromNum[0]), parseNum(@toNum[0])] if from <= to then "#{lt} #{to}" else "#{gt} #{to}" else cond = if @stepVar then "#{@stepVar} > 0" else "#{@fromVar} <= #{@toVar}" "#{cond} ? #{lt} #{@toVar} : #{gt} #{@toVar}" # Generate the step. stepPart = if @stepVar "#{idx} += #{@stepVar}" else if known if namedIndex if from <= to then "++#{idx}" else "--#{idx}" else if from <= to then "#{idx}++" else "#{idx}--" else if namedIndex "#{cond} ? ++#{idx} : --#{idx}" else "#{cond} ? #{idx}++ : #{idx}--" varPart = "#{idxName} = #{varPart}" if namedIndex stepPart = "#{idxName} = #{stepPart}" if namedIndex # The final loop body. [@makeCode "#{varPart}; #{condPart}; #{stepPart}"] # When used as a value, expand the range into the equivalent array. compileArray: (o) -> if @fromNum and @toNum and Math.abs(@fromNum - @toNum) <= 20 range = [+@fromNum..+@toNum] range.pop() if @exclusive return [@makeCode "[#{ range.join(', ') }]"] idt = @tab + TAB i = o.scope.freeVariable 'i', single: true result = o.scope.freeVariable 'results' pre = "\n#{idt}#{result} = [];" if @fromNum and @toNum o.index = i body = fragmentsToText @compileNode o else vars = "#{i} = #{@fromC}" + if @toC isnt @toVar then ", #{@toC}" else '' cond = "#{@fromVar} <= #{@toVar}" body = "var #{vars}; #{cond} ? #{i} <#{@equals} #{@toVar} : #{i} >#{@equals} #{@toVar}; #{cond} ? #{i}++ : #{i}--" post = "{ #{result}.push(#{i}); }\n#{idt}return #{result};\n#{o.indent}" hasArgs = (node) -> node?.contains isLiteralArguments args = ', arguments' if hasArgs(@from) or hasArgs(@to) [@makeCode "(function() {#{pre}\n#{idt}for (#{body})#{post}}).apply(this#{args ? ''})"] #### Slice # An array slice literal. Unlike JavaScript's `Array#slice`, the second parameter # specifies the index of the end of the slice, just as the first parameter # is the index of the beginning. exports.Slice = class Slice extends Base children: ['range'] constructor: (@range) -> super() # We have to be careful when trying to slice through the end of the array, # `9e9` is used because not all implementations respect `undefined` or `1/0`. # `9e9` should be safe because `9e9` > `2**32`, the max array length. compileNode: (o) -> {to, from} = @range fromCompiled = from and from.compileToFragments(o, LEVEL_PAREN) or [@makeCode '0'] # TODO: jwalton - move this into the 'if'? if to compiled = to.compileToFragments o, LEVEL_PAREN compiledText = fragmentsToText compiled if not (not @range.exclusive and +compiledText is -1) toStr = ', ' + if @range.exclusive compiledText else if SIMPLENUM.test compiledText "#{+compiledText + 1}" else compiled = to.compileToFragments o, LEVEL_ACCESS "+#{fragmentsToText compiled} + 1 || 9e9" [@makeCode ".slice(#{ fragmentsToText fromCompiled }#{ toStr or '' })"] #### Obj # An object literal, nothing fancy. exports.Obj = class Obj extends Base constructor: (props, @generated = false) -> @objects = @properties = props or [] children: ['properties'] compileNode: (o) -> props = @properties if @generated for node in props when node instanceof Value node.error 'cannot have an implicit value in an implicit object' break for prop, dynamicIndex in props when (prop.variable or prop).base instanceof Parens hasDynamic = dynamicIndex < props.length idt = o.indent += TAB lastNoncom = @lastNonComment @properties answer = [] if hasDynamic oref = o.scope.freeVariable 'obj' answer.push @makeCode "(\n#{idt}#{oref} = " answer.push @makeCode "{#{if props.length is 0 or dynamicIndex is 0 then '}' else '\n'}" for prop, i in props if i is dynamicIndex answer.push @makeCode "\n#{idt}}" unless i is 0 answer.push @makeCode ',\n' join = if i is props.length - 1 or i is dynamicIndex - 1 '' else if prop is lastNoncom or prop instanceof Comment '\n' else ',\n' indent = if prop instanceof Comment then '' else idt indent += TAB if hasDynamic and i < dynamicIndex if prop instanceof Assign and prop.variable instanceof Value and prop.variable.hasProperties() prop.variable.error 'invalid object key' if prop instanceof Value and prop.this prop = new Assign prop.properties[0].name, prop, 'object' if prop not instanceof Comment if i < dynamicIndex if prop not instanceof Assign prop = new Assign prop, prop, 'object' (prop.variable.base or prop.variable).asKey = yes else if prop instanceof Assign key = prop.variable value = prop.value else [key, value] = prop.base.cache o prop = new Assign (new Value (new Literal oref), [new Access key]), value if indent then answer.push @makeCode indent answer.push prop.compileToFragments(o, LEVEL_TOP)... if join then answer.push @makeCode join if hasDynamic answer.push @makeCode ",\n#{idt}#{oref}\n#{@tab})" else answer.push @makeCode "\n#{@tab}}" unless props.length is 0 if @front and not hasDynamic then @wrapInBraces answer else answer assigns: (name) -> for prop in @properties when prop.assigns name then return yes no #### Arr # An array literal. exports.Arr = class Arr extends Base constructor: (objs) -> @objects = objs or [] children: ['objects'] compileNode: (o) -> return [@makeCode '[]'] unless @objects.length o.indent += TAB answer = Splat.compileSplattedArray o, @objects return answer if answer.length answer = [] compiledObjs = (obj.compileToFragments o, LEVEL_LIST for obj in @objects) for fragments, index in compiledObjs if index answer.push @makeCode ", " answer.push fragments... if fragmentsToText(answer).indexOf('\n') >= 0 answer.unshift @makeCode "[\n#{o.indent}" answer.push @makeCode "\n#{@tab}]" else answer.unshift @makeCode "[" answer.push @makeCode "]" answer assigns: (name) -> for obj in @objects when obj.assigns name then return yes no #### Class # The CoffeeScript class definition. # Initialize a **Class** with its name, an optional superclass, and a # list of prototype property assignments. exports.Class = class Class extends Base constructor: (@variable, @parent, @body = new Block) -> @boundFuncs = [] @body.classBody = yes children: ['variable', 'parent', 'body'] # Figure out the appropriate name for the constructor function of this class. determineName: -> return null unless @variable [..., tail] = @variable.properties decl = if tail tail instanceof Access and tail.name.value else @variable.base.value if decl in STRICT_PROSCRIBED @variable.error "class variable name may not be #{decl}" decl and= IDENTIFIER.test(decl) and decl # For all `this`-references and bound functions in the class definition, # `this` is the Class being constructed. setContext: (name) -> @body.traverseChildren false, (node) -> return false if node.classBody if node instanceof Literal and node.value is 'this' node.value = name else if node instanceof Code node.context = name if node.bound # Ensure that all functions bound to the instance are proxied in the # constructor. addBoundFunctions: (o) -> for bvar in @boundFuncs lhs = (new Value (new Literal "this"), [new Access bvar]).compile o @ctor.body.unshift new Literal "#{lhs} = #{utility 'bind', o}(#{lhs}, this)" return # Merge the properties from a top-level object as prototypal properties # on the class. addProperties: (node, name, o) -> props = node.base.properties[..] exprs = while assign = props.shift() if assign instanceof Assign base = assign.variable.base delete assign.context func = assign.value if base.value is 'constructor' if @ctor assign.error 'cannot define more than one constructor in a class' if func.bound assign.error 'cannot define a constructor as a bound function' if func instanceof Code assign = @ctor = func else @externalCtor = o.classScope.freeVariable 'class' assign = new Assign new Literal(@externalCtor), func else if assign.variable.this func.static = yes else acc = if base.isComplex() then new Index base else new Access base assign.variable = new Value(new Literal(name), [(new Access new Literal 'prototype'), acc]) if func instanceof Code and func.bound @boundFuncs.push base func.bound = no assign compact exprs # Walk the body of the class, looking for prototype properties to be converted # and tagging static assignments. walkBody: (name, o) -> @traverseChildren false, (child) => cont = true return false if child instanceof Class if child instanceof Block for node, i in exps = child.expressions if node instanceof Assign and node.variable.looksStatic name node.value.static = yes else if node instanceof Value and node.isObject(true) cont = false exps[i] = @addProperties node, name, o child.expressions = exps = flatten exps cont and child not instanceof Class # `use strict` (and other directives) must be the first expression statement(s) # of a function body. This method ensures the prologue is correctly positioned # above the `constructor`. hoistDirectivePrologue: -> index = 0 {expressions} = @body ++index while (node = expressions[index]) and node instanceof Comment or node instanceof Value and node.isString() @directives = expressions.splice 0, index # Make sure that a constructor is defined for the class, and properly # configured. ensureConstructor: (name) -> if not @ctor @ctor = new Code if @externalCtor @ctor.body.push new Literal "#{@externalCtor}.apply(this, arguments)" else if @parent @ctor.body.push new Literal "#{name}.__super__.constructor.apply(this, arguments)" @ctor.body.makeReturn() @body.expressions.unshift @ctor @ctor.ctor = @ctor.name = name @ctor.klass = null @ctor.noReturn = yes # Instead of generating the JavaScript string directly, we build up the # equivalent syntax tree and compile that, in pieces. You can see the # constructor, property assignments, and inheritance getting built out below. compileNode: (o) -> if jumpNode = @body.jumps() jumpNode.error 'Class bodies cannot contain pure statements' if argumentsNode = @body.contains isLiteralArguments argumentsNode.error "Class bodies shouldn't reference arguments" name = @determineName() or '_Class' name = "_#{name}" if name.reserved lname = new Literal name func = new Code [], Block.wrap [@body] args = [] o.classScope = func.makeScope o.scope @hoistDirectivePrologue() @setContext name @walkBody name, o @ensureConstructor name @addBoundFunctions o @body.spaced = yes @body.expressions.push lname if @parent superClass = new Literal o.classScope.freeVariable 'superClass', reserve: no @body.expressions.unshift new Extends lname, superClass func.params.push new Param superClass args.push @parent @body.expressions.unshift @directives... klass = new Parens new Call func, args klass = new Assign @variable, klass if @variable klass.compileToFragments o #### Assign # The **Assign** is used to assign a local variable to value, or to set the # property of an object -- including within object literals. exports.Assign = class Assign extends Base constructor: (@variable, @value, @context, options) -> @param = options and options.param @subpattern = options and options.subpattern forbidden = (name = @variable.unwrapAll().value) in STRICT_PROSCRIBED if forbidden and @context isnt 'object' @variable.error "variable name may not be \"#{name}\"" children: ['variable', 'value'] isStatement: (o) -> o?.level is LEVEL_TOP and @context? and "?" in @context assigns: (name) -> @[if @context is 'object' then 'value' else 'variable'].assigns name unfoldSoak: (o) -> unfoldSoak o, this, 'variable' # Compile an assignment, delegating to `compilePatternMatch` or # `compileSplice` if appropriate. Keep track of the name of the base object # we've been assigned to, for correct internal references. If the variable # has not been seen yet within the current scope, declare it. compileNode: (o) -> if isValue = @variable instanceof Value return @compilePatternMatch o if @variable.isArray() or @variable.isObject() return @compileSplice o if @variable.isSplice() return @compileConditional o if @context in ['||=', '&&=', '?='] return @compileSpecialMath o if @context in ['**=', '//=', '%%='] if @value instanceof Code if @value.static @value.klass = @variable.base @value.name = @variable.properties[0] @value.variable = @variable else if @variable.properties?.length >= 2 [properties..., prototype, name] = @variable.properties if prototype.name?.value is 'prototype' @value.klass = new Value @variable.base, properties @value.name = name @value.variable = @variable unless @context varBase = @variable.unwrapAll() unless varBase.isAssignable() @variable.error "\"#{@variable.compile o}\" cannot be assigned" unless varBase.hasProperties?() if @param o.scope.add varBase.value, 'var' else o.scope.find varBase.value val = @value.compileToFragments o, LEVEL_LIST compiledName = @variable.compileToFragments o, LEVEL_LIST return (compiledName.concat @makeCode(": "), val) if @context is 'object' answer = compiledName.concat @makeCode(" #{ @context or '=' } "), val if o.level <= LEVEL_LIST then answer else @wrapInBraces answer # Brief implementation of recursive pattern matching, when assigning array or # object literals to a value. Peeks at their properties to assign inner names. # See the [ECMAScript Harmony Wiki](http://wiki.ecmascript.org/doku.php?id=harmony:destructuring) # for details. compilePatternMatch: (o) -> top = o.level is LEVEL_TOP {value} = this {objects} = @variable.base unless olen = objects.length code = value.compileToFragments o return if o.level >= LEVEL_OP then @wrapInBraces code else code isObject = @variable.isObject() if top and olen is 1 and (obj = objects[0]) not instanceof Splat # Unroll simplest cases: `{v} = x` -> `v = x.v` if obj instanceof Assign {variable: {base: idx}, value: obj} = obj else idx = if isObject if obj.this then obj.properties[0].name else obj else new Literal 0 acc = IDENTIFIER.test idx.unwrap().value or 0 value = new Value value value.properties.push new (if acc then Access else Index) idx if obj.unwrap().value in RESERVED obj.error "assignment to a reserved word: #{obj.compile o}" return new Assign(obj, value, null, param: @param).compileToFragments o, LEVEL_TOP vvar = value.compileToFragments o, LEVEL_LIST vvarText = fragmentsToText vvar assigns = [] expandedIdx = false # Make vvar into a simple variable if it isn't already. if not IDENTIFIER.test(vvarText) or @variable.assigns(vvarText) assigns.push [@makeCode("#{ ref = o.scope.freeVariable 'ref' } = "), vvar...] vvar = [@makeCode ref] vvarText = ref for obj, i in objects # A regular array pattern-match. idx = i if isObject if obj instanceof Assign # A regular object pattern-match. {variable: {base: idx}, value: obj} = obj else # A shorthand `{a, b, @c} = val` pattern-match. if obj.base instanceof Parens [obj, idx] = new Value(obj.unwrapAll()).cacheReference o else idx = if obj.this then obj.properties[0].name else obj if not expandedIdx and obj instanceof Splat name = obj.name.unwrap().value obj = obj.unwrap() val = "#{olen} <= #{vvarText}.length ? #{ utility 'slice', o }.call(#{vvarText}, #{i}" if rest = olen - i - 1 ivar = o.scope.freeVariable 'i', single: true val += ", #{ivar} = #{vvarText}.length - #{rest}) : (#{ivar} = #{i}, [])" else val += ") : []" val = new Literal val expandedIdx = "#{ivar}++" else if not expandedIdx and obj instanceof Expansion if rest = olen - i - 1 if rest is 1 expandedIdx = "#{vvarText}.length - 1" else ivar = o.scope.freeVariable 'i', single: true val = new Literal "#{ivar} = #{vvarText}.length - #{rest}" expandedIdx = "#{ivar}++" assigns.push val.compileToFragments o, LEVEL_LIST continue else name = obj.unwrap().value if obj instanceof Splat or obj instanceof Expansion obj.error "multiple splats/expansions are disallowed in an assignment" if typeof idx is 'number' idx = new Literal expandedIdx or idx acc = no else acc = isObject and IDENTIFIER.test idx.unwrap().value or 0 val = new Value new Literal(vvarText), [new (if acc then Access else Index) idx] if name? and name in RESERVED obj.error "assignment to a reserved word: #{obj.compile o}" assigns.push new Assign(obj, val, null, param: @param, subpattern: yes).compileToFragments o, LEVEL_LIST assigns.push vvar unless top or @subpattern fragments = @joinFragmentArrays assigns, ', ' if o.level < LEVEL_LIST then fragments else @wrapInBraces fragments # When compiling a conditional assignment, take care to ensure that the # operands are only evaluated once, even though we have to reference them # more than once. compileConditional: (o) -> [left, right] = @variable.cacheReference o # Disallow conditional assignment of undefined variables. if not left.properties.length and left.base instanceof Literal and left.base.value != "this" and not o.scope.check left.base.value @variable.error "the variable \"#{left.base.value}\" can't be assigned with #{@context} because it has not been declared before" if "?" in @context o.isExistentialEquals = true new If(new Existence(left), right, type: 'if').addElse(new Assign(right, @value, '=')).compileToFragments o else fragments = new Op(@context[...-1], left, new Assign(right, @value, '=')).compileToFragments o if o.level <= LEVEL_LIST then fragments else @wrapInBraces fragments # Convert special math assignment operators like `a **= b` to the equivalent # extended form `a = a ** b` and then compiles that. compileSpecialMath: (o) -> [left, right] = @variable.cacheReference o new Assign(left, new Op(@context[...-1], right, @value)).compileToFragments o # Compile the assignment from an array splice literal, using JavaScript's # `Array#splice` method. compileSplice: (o) -> {range: {from, to, exclusive}} = @variable.properties.pop() name = @variable.compile o if from [fromDecl, fromRef] = @cacheToCodeFragments from.cache o, LEVEL_OP else fromDecl = fromRef = '0' if to if from instanceof Value and from.isSimpleNumber() and to instanceof Value and to.isSimpleNumber() to = to.compile(o) - fromRef to += 1 unless exclusive else to = to.compile(o, LEVEL_ACCESS) + ' - ' + fromRef to += ' + 1' unless exclusive else to = "9e9" [valDef, valRef] = @value.cache o, LEVEL_LIST answer = [].concat @makeCode("[].splice.apply(#{name}, [#{fromDecl}, #{to}].concat("), valDef, @makeCode(")), "), valRef if o.level > LEVEL_TOP then @wrapInBraces answer else answer #### Code # A function definition. This is the only node that creates a new Scope. # When for the purposes of walking the contents of a function body, the Code # has no *children* -- they're within the inner scope. exports.Code = class Code extends Base constructor: (params, body, tag) -> @params = params or [] @body = body or new Block @bound = tag is 'boundfunc' @isGenerator = !!@body.contains (node) -> node instanceof Op and node.operator in ['yield', 'yield*'] children: ['params', 'body'] isStatement: -> !!@ctor jumps: NO makeScope: (parentScope) -> new Scope parentScope, @body, this # Compilation creates a new scope unless explicitly asked to share with the # outer scope. Handles splat parameters in the parameter list by peeking at # the JavaScript `arguments` object. If the function is bound with the `=>` # arrow, generates a wrapper that saves the current value of `this` through # a closure. compileNode: (o) -> if @bound and o.scope.method?.bound @context = o.scope.method.context # Handle bound functions early. if @bound and not @context @context = '_this' wrapper = new Code [new Param new Literal @context], new Block [this] boundfunc = new Call(wrapper, [new Literal 'this']) boundfunc.updateLocationDataIfMissing @locationData return boundfunc.compileNode(o) o.scope = del(o, 'classScope') or @makeScope o.scope o.scope.shared = del(o, 'sharedScope') o.indent += TAB delete o.bare delete o.isExistentialEquals params = [] exprs = [] for param in @params when param not instanceof Expansion o.scope.parameter param.asReference o for param in @params when param.splat or param instanceof Expansion for p in @params when p not instanceof Expansion and p.name.value o.scope.add p.name.value, 'var', yes splats = new Assign new Value(new Arr(p.asReference o for p in @params)), new Value new Literal 'arguments' break for param in @params if param.isComplex() val = ref = param.asReference o val = new Op '?', ref, param.value if param.value exprs.push new Assign new Value(param.name), val, '=', param: yes else ref = param if param.value lit = new Literal ref.name.value + ' == null' val = new Assign new Value(param.name), param.value, '=' exprs.push new If lit, val params.push ref unless splats wasEmpty = @body.isEmpty() exprs.unshift splats if splats @body.expressions.unshift exprs... if exprs.length for p, i in params params[i] = p.compileToFragments o o.scope.parameter fragmentsToText params[i] uniqs = [] @eachParamName (name, node) -> node.error "multiple parameters named #{name}" if name in uniqs uniqs.push name @body.makeReturn() unless wasEmpty or @noReturn code = 'function' code += '*' if @isGenerator code += ' ' + @name if @ctor code += '(' answer = [@makeCode(code)] for p, i in params if i then answer.push @makeCode ", " answer.push p... answer.push @makeCode ') {' answer = answer.concat(@makeCode("\n"), @body.compileWithDeclarations(o), @makeCode("\n#{@tab}")) unless @body.isEmpty() answer.push @makeCode '}' return [@makeCode(@tab), answer...] if @ctor if @front or (o.level >= LEVEL_ACCESS) then @wrapInBraces answer else answer eachParamName: (iterator) -> param.eachName iterator for param in @params # Short-circuit `traverseChildren` method to prevent it from crossing scope boundaries # unless `crossScope` is `true`. traverseChildren: (crossScope, func) -> super(crossScope, func) if crossScope #### Param # A parameter in a function definition. Beyond a typical Javascript parameter, # these parameters can also attach themselves to the context of the function, # as well as be a splat, gathering up a group of parameters into an array. exports.Param = class Param extends Base constructor: (@name, @value, @splat) -> if (name = @name.unwrapAll().value) in STRICT_PROSCRIBED @name.error "parameter name \"#{name}\" is not allowed" children: ['name', 'value'] compileToFragments: (o) -> @name.compileToFragments o, LEVEL_LIST asReference: (o) -> return @reference if @reference node = @name if node.this name = node.properties[0].name.value name = "_#{name}" if name.reserved node = new Literal o.scope.freeVariable name else if node.isComplex() node = new Literal o.scope.freeVariable 'arg' node = new Value node node = new Splat node if @splat node.updateLocationDataIfMissing @locationData @reference = node isComplex: -> @name.isComplex() # Iterates the name or names of a `Param`. # In a sense, a destructured parameter represents multiple JS parameters. This # method allows to iterate them all. # The `iterator` function will be called as `iterator(name, node)` where # `name` is the name of the parameter and `node` is the AST node corresponding # to that name. eachName: (iterator, name = @name)-> atParam = (obj) -> iterator "@#{obj.properties[0].name.value}", obj # * simple literals `foo` return iterator name.value, name if name instanceof Literal # * at-params `@foo` return atParam name if name instanceof Value for obj in name.objects # * assignments within destructured parameters `{foo:bar}` if obj instanceof Assign @eachName iterator, obj.value.unwrap() # * splats within destructured parameters `[xs...]` else if obj instanceof Splat node = obj.name.unwrap() iterator node.value, node else if obj instanceof Value # * destructured parameters within destructured parameters `[{a}]` if obj.isArray() or obj.isObject() @eachName iterator, obj.base # * at-params within destructured parameters `{@foo}` else if obj.this atParam obj # * simple destructured parameters {foo} else iterator obj.base.value, obj.base else if obj not instanceof Expansion obj.error "illegal parameter #{obj.compile()}" return #### Splat # A splat, either as a parameter to a function, an argument to a call, # or as part of a destructuring assignment. exports.Splat = class Splat extends Base children: ['name'] isAssignable: YES constructor: (name) -> @name = if name.compile then name else new Literal name assigns: (name) -> @name.assigns name compileToFragments: (o) -> @name.compileToFragments o unwrap: -> @name # Utility function that converts an arbitrary number of elements, mixed with # splats, to a proper array. @compileSplattedArray: (o, list, apply) -> index = -1 continue while (node = list[++index]) and node not instanceof Splat return [] if index >= list.length if list.length is 1 node = list[0] fragments = node.compileToFragments o, LEVEL_LIST return fragments if apply return [].concat node.makeCode("#{ utility 'slice', o }.call("), fragments, node.makeCode(")") args = list[index..] for node, i in args compiledNode = node.compileToFragments o, LEVEL_LIST args[i] = if node instanceof Splat then [].concat node.makeCode("#{ utility 'slice', o }.call("), compiledNode, node.makeCode(")") else [].concat node.makeCode("["), compiledNode, node.makeCode("]") if index is 0 node = list[0] concatPart = (node.joinFragmentArrays args[1..], ', ') return args[0].concat node.makeCode(".concat("), concatPart, node.makeCode(")") base = (node.compileToFragments o, LEVEL_LIST for node in list[...index]) base = list[0].joinFragmentArrays base, ', ' concatPart = list[index].joinFragmentArrays args, ', ' [..., last] = list [].concat list[0].makeCode("["), base, list[index].makeCode("].concat("), concatPart, last.makeCode(")") #### Expansion # Used to skip values inside an array destructuring (pattern matching) or # parameter list. exports.Expansion = class Expansion extends Base isComplex: NO compileNode: (o) -> @error 'Expansion must be used inside a destructuring assignment or parameter list' asReference: (o) -> this eachName: (iterator) -> #### While # A while loop, the only sort of low-level loop exposed by CoffeeScript. From # it, all other loops can be manufactured. Useful in cases where you need more # flexibility or more speed than a comprehension can provide. exports.While = class While extends Base constructor: (condition, options) -> @condition = if options?.invert then condition.invert() else condition @guard = options?.guard children: ['condition', 'guard', 'body'] isStatement: YES makeReturn: (res) -> if res super else @returns = not @jumps loop: yes this addBody: (@body) -> this jumps: -> {expressions} = @body return no unless expressions.length for node in expressions return jumpNode if jumpNode = node.jumps loop: yes no # The main difference from a JavaScript *while* is that the CoffeeScript # *while* can be used as a part of a larger expression -- while loops may # return an array containing the computed result of each iteration. compileNode: (o) -> o.indent += TAB set = '' {body} = this if body.isEmpty() body = @makeCode '' else if @returns body.makeReturn rvar = o.scope.freeVariable 'results' set = "#{@tab}#{rvar} = [];\n" if @guard if body.expressions.length > 1 body.expressions.unshift new If (new Parens @guard).invert(), new Literal "continue" else body = Block.wrap [new If @guard, body] if @guard body = [].concat @makeCode("\n"), (body.compileToFragments o, LEVEL_TOP), @makeCode("\n#{@tab}") answer = [].concat @makeCode(set + @tab + "while ("), @condition.compileToFragments(o, LEVEL_PAREN), @makeCode(") {"), body, @makeCode("}") if @returns answer.push @makeCode "\n#{@tab}return #{rvar};" answer #### Op # Simple Arithmetic and logical operations. Performs some conversion from # CoffeeScript operations into their JavaScript equivalents. exports.Op = class Op extends Base constructor: (op, first, second, flip ) -> return new In first, second if op is 'in' if op is 'do' return @generateDo first if op is 'new' return first.newInstance() if first instanceof Call and not first.do and not first.isNew first = new Parens first if first instanceof Code and first.bound or first.do @operator = CONVERSIONS[op] or op @first = first @second = second @flip = !!flip return this # The map of conversions from CoffeeScript to JavaScript symbols. CONVERSIONS = '==': '===' '!=': '!==' 'of': 'in' 'yieldfrom': 'yield*' # The map of invertible operators. INVERSIONS = '!==': '===' '===': '!==' children: ['first', 'second'] isSimpleNumber: NO isYield: -> @operator in ['yield', 'yield*'] isYieldReturn: -> @isYield() and @first instanceof Return isUnary: -> not @second isComplex: -> not (@isUnary() and @operator in ['+', '-'] and @first instanceof Value and @first.isSimpleNumber()) # Am I capable of # [Python-style comparison chaining](http://docs.python.org/reference/expressions.html#notin)? isChainable: -> @operator in ['<', '>', '>=', '<=', '===', '!=='] invert: -> if @isChainable() and @first.isChainable() allInvertable = yes curr = this while curr and curr.operator allInvertable and= (curr.operator of INVERSIONS) curr = curr.first return new Parens(this).invert() unless allInvertable curr = this while curr and curr.operator curr.invert = !curr.invert curr.operator = INVERSIONS[curr.operator] curr = curr.first this else if op = INVERSIONS[@operator] @operator = op if @first.unwrap() instanceof Op @first.invert() this else if @second new Parens(this).invert() else if @operator is '!' and (fst = @first.unwrap()) instanceof Op and fst.operator in ['!', 'in', 'instanceof'] fst else new Op '!', this unfoldSoak: (o) -> @operator in ['++', '--', 'delete'] and unfoldSoak o, this, 'first' generateDo: (exp) -> passedParams = [] func = if exp instanceof Assign and (ref = exp.value.unwrap()) instanceof Code ref else exp for param in func.params or [] if param.value passedParams.push param.value delete param.value else passedParams.push param call = new Call exp, passedParams call.do = yes call compileNode: (o) -> isChain = @isChainable() and @first.isChainable() # In chains, there's no need to wrap bare obj literals in parens, # as the chained expression is wrapped. @first.front = @front unless isChain if @operator is 'delete' and o.scope.check(@first.unwrapAll().value) @error 'delete operand may not be argument or var' if @operator in ['--', '++'] and @first.unwrapAll().value in STRICT_PROSCRIBED @error "cannot increment/decrement \"#{@first.unwrapAll().value}\"" return @compileYield o if @isYield() return @compileUnary o if @isUnary() return @compileChain o if isChain switch @operator when '?' then @compileExistence o when '**' then @compilePower o when '//' then @compileFloorDivision o when '%%' then @compileModulo o else lhs = @first.compileToFragments o, LEVEL_OP rhs = @second.compileToFragments o, LEVEL_OP answer = [].concat lhs, @makeCode(" #{@operator} "), rhs if o.level <= LEVEL_OP then answer else @wrapInBraces answer # Mimic Python's chained comparisons when multiple comparison operators are # used sequentially. For example: # # bin/coffee -e 'console.log 50 < 65 > 10' # true compileChain: (o) -> [@first.second, shared] = @first.second.cache o fst = @first.compileToFragments o, LEVEL_OP fragments = fst.concat @makeCode(" #{if @invert then '&&' else '||'} "), (shared.compileToFragments o), @makeCode(" #{@operator} "), (@second.compileToFragments o, LEVEL_OP) @wrapInBraces fragments # Keep reference to the left expression, unless this an existential assignment compileExistence: (o) -> if @first.isComplex() ref = new Literal o.scope.freeVariable 'ref' fst = new Parens new Assign ref, @first else fst = @first ref = fst new If(new Existence(fst), ref, type: 'if').addElse(@second).compileToFragments o # Compile a unary **Op**. compileUnary: (o) -> parts = [] op = @operator parts.push [@makeCode op] if op is '!' and @first instanceof Existence @first.negated = not @first.negated return @first.compileToFragments o if o.level >= LEVEL_ACCESS return (new Parens this).compileToFragments o plusMinus = op in ['+', '-'] parts.push [@makeCode(' ')] if op in ['new', 'typeof', 'delete'] or plusMinus and @first instanceof Op and @first.operator is op if (plusMinus and @first instanceof Op) or (op is 'new' and @first.isStatement o) @first = new Parens @first parts.push @first.compileToFragments o, LEVEL_OP parts.reverse() if @flip @joinFragmentArrays parts, '' compileYield: (o) -> parts = [] op = @operator if not o.scope.parent? @error 'yield statements must occur within a function generator.' if 'expression' in Object.keys(@first) and not (@first instanceof Throw) if @isYieldReturn() parts.push @first.compileToFragments o, LEVEL_TOP else if @first.expression? parts.push @first.expression.compileToFragments o, LEVEL_OP else parts.push [@makeCode "(#{op} "] parts.push @first.compileToFragments o, LEVEL_OP parts.push [@makeCode ")"] @joinFragmentArrays parts, '' compilePower: (o) -> # Make a Math.pow call pow = new Value new Literal('Math'), [new Access new Literal 'pow'] new Call(pow, [@first, @second]).compileToFragments o compileFloorDivision: (o) -> floor = new Value new Literal('Math'), [new Access new Literal 'floor'] div = new Op '/', @first, @second new Call(floor, [div]).compileToFragments o compileModulo: (o) -> mod = new Value new Literal utility 'modulo', o new Call(mod, [@first, @second]).compileToFragments o toString: (idt) -> super idt, @constructor.name + ' ' + @operator #### In exports.In = class In extends Base constructor: (@object, @array) -> children: ['object', 'array'] invert: NEGATE compileNode: (o) -> if @array instanceof Value and @array.isArray() and @array.base.objects.length for obj in @array.base.objects when obj instanceof Splat hasSplat = yes break # `compileOrTest` only if we have an array literal with no splats return @compileOrTest o unless hasSplat @compileLoopTest o compileOrTest: (o) -> [sub, ref] = @object.cache o, LEVEL_OP [cmp, cnj] = if @negated then [' !== ', ' && '] else [' === ', ' || '] tests = [] for item, i in @array.base.objects if i then tests.push @makeCode cnj tests = tests.concat (if i then ref else sub), @makeCode(cmp), item.compileToFragments(o, LEVEL_ACCESS) if o.level < LEVEL_OP then tests else @wrapInBraces tests compileLoopTest: (o) -> [sub, ref] = @object.cache o, LEVEL_LIST fragments = [].concat @makeCode(utility('indexOf', o) + ".call("), @array.compileToFragments(o, LEVEL_LIST), @makeCode(", "), ref, @makeCode(") " + if @negated then '< 0' else '>= 0') return fragments if fragmentsToText(sub) is fragmentsToText(ref) fragments = sub.concat @makeCode(', '), fragments if o.level < LEVEL_LIST then fragments else @wrapInBraces fragments toString: (idt) -> super idt, @constructor.name + if @negated then '!' else '' #### Try # A classic *try/catch/finally* block. exports.Try = class Try extends Base constructor: (@attempt, @errorVariable, @recovery, @ensure) -> children: ['attempt', 'recovery', 'ensure'] isStatement: YES jumps: (o) -> @attempt.jumps(o) or @recovery?.jumps(o) makeReturn: (res) -> @attempt = @attempt .makeReturn res if @attempt @recovery = @recovery.makeReturn res if @recovery this # Compilation is more or less as you would expect -- the *finally* clause # is optional, the *catch* is not. compileNode: (o) -> o.indent += TAB tryPart = @attempt.compileToFragments o, LEVEL_TOP catchPart = if @recovery placeholder = new Literal '_error' @recovery.unshift new Assign @errorVariable, placeholder if @errorVariable [].concat @makeCode(" catch ("), placeholder.compileToFragments(o), @makeCode(") {\n"), @recovery.compileToFragments(o, LEVEL_TOP), @makeCode("\n#{@tab}}") else unless @ensure or @recovery [@makeCode(' catch (_error) {}')] else [] ensurePart = if @ensure then ([].concat @makeCode(" finally {\n"), @ensure.compileToFragments(o, LEVEL_TOP), @makeCode("\n#{@tab}}")) else [] [].concat @makeCode("#{@tab}try {\n"), tryPart, @makeCode("\n#{@tab}}"), catchPart, ensurePart #### Throw # Simple node to throw an exception. exports.Throw = class Throw extends Base constructor: (@expression) -> children: ['expression'] isStatement: YES jumps: NO # A **Throw** is already a return, of sorts... makeReturn: THIS compileNode: (o) -> [].concat @makeCode(@tab + "throw "), @expression.compileToFragments(o), @makeCode(";") #### Existence # Checks a variable for existence -- not *null* and not *undefined*. This is # similar to `.nil?` in Ruby, and avoids having to consult a JavaScript truth # table. exports.Existence = class Existence extends Base constructor: (@expression) -> children: ['expression'] invert: NEGATE compileNode: (o) -> @expression.front = @front code = @expression.compile o, LEVEL_OP if IDENTIFIER.test(code) and not o.scope.check code [cmp, cnj] = if @negated then ['===', '||'] else ['!==', '&&'] code = "typeof #{code} #{cmp} \"undefined\" #{cnj} #{code} #{cmp} null" else # do not use strict equality here; it will break existing code code = "#{code} #{if @negated then '==' else '!='} null" [@makeCode(if o.level <= LEVEL_COND then code else "(#{code})")] #### Parens # An extra set of parentheses, specified explicitly in the source. At one time # we tried to clean up the results by detecting and removing redundant # parentheses, but no longer -- you can put in as many as you please. # # Parentheses are a good way to force any statement to become an expression. exports.Parens = class Parens extends Base constructor: (@body) -> children: ['body'] unwrap : -> @body isComplex : -> @body.isComplex() compileNode: (o) -> expr = @body.unwrap() if expr instanceof Value and expr.isAtomic() expr.front = @front return expr.compileToFragments o fragments = expr.compileToFragments o, LEVEL_PAREN bare = o.level < LEVEL_OP and (expr instanceof Op or expr instanceof Call or (expr instanceof For and expr.returns)) if bare then fragments else @wrapInBraces fragments #### For # CoffeeScript's replacement for the *for* loop is our array and object # comprehensions, that compile into *for* loops here. They also act as an # expression, able to return the result of each filtered iteration. # # Unlike Python array comprehensions, they can be multi-line, and you can pass # the current index of the loop as a second parameter. Unlike Ruby blocks, # you can map and filter in a single pass. exports.For = class For extends While constructor: (body, source) -> {@source, @guard, @step, @name, @index} = source @body = Block.wrap [body] @own = !!source.own @object = !!source.object [@name, @index] = [@index, @name] if @object @index.error 'index cannot be a pattern matching expression' if @index instanceof Value @range = @source instanceof Value and @source.base instanceof Range and not @source.properties.length @pattern = @name instanceof Value @index.error 'indexes do not apply to range loops' if @range and @index @name.error 'cannot pattern match over range loops' if @range and @pattern @name.error 'cannot use own with for-in' if @own and not @object @returns = false children: ['body', 'source', 'guard', 'step'] # Welcome to the hairiest method in all of CoffeeScript. Handles the inner # loop, filtering, stepping, and result saving for array, object, and range # comprehensions. Some of the generated code can be shared in common, and # some cannot. compileNode: (o) -> body = Block.wrap [@body] [..., last] = body.expressions @returns = no if last?.jumps() instanceof Return source = if @range then @source.base else @source scope = o.scope name = @name and (@name.compile o, LEVEL_LIST) if not @pattern index = @index and (@index.compile o, LEVEL_LIST) scope.find(name) if name and not @pattern scope.find(index) if index rvar = scope.freeVariable 'results' if @returns ivar = (@object and index) or scope.freeVariable 'i', single: true kvar = (@range and name) or index or ivar kvarAssign = if kvar isnt ivar then "#{kvar} = " else "" if @step and not @range [step, stepVar] = @cacheToCodeFragments @step.cache o, LEVEL_LIST, isComplexOrAssignable stepNum = stepVar.match NUMBER name = ivar if @pattern varPart = '' guardPart = '' defPart = '' idt1 = @tab + TAB if @range forPartFragments = source.compileToFragments merge o, {index: ivar, name, @step, isComplex: isComplexOrAssignable} else svar = @source.compile o, LEVEL_LIST if (name or @own) and not IDENTIFIER.test svar defPart += "#{@tab}#{ref = scope.freeVariable 'ref'} = #{svar};\n" svar = ref if name and not @pattern namePart = "#{name} = #{svar}[#{kvar}]" if not @object defPart += "#{@tab}#{step};\n" if step isnt stepVar lvar = scope.freeVariable 'len' unless @step and stepNum and down = (parseNum(stepNum[0]) < 0) declare = "#{kvarAssign}#{ivar} = 0, #{lvar} = #{svar}.length" declareDown = "#{kvarAssign}#{ivar} = #{svar}.length - 1" compare = "#{ivar} < #{lvar}" compareDown = "#{ivar} >= 0" if @step if stepNum if down compare = compareDown declare = declareDown else compare = "#{stepVar} > 0 ? #{compare} : #{compareDown}" declare = "(#{stepVar} > 0 ? (#{declare}) : #{declareDown})" increment = "#{ivar} += #{stepVar}" else increment = "#{if kvar isnt ivar then "++#{ivar}" else "#{ivar}++"}" forPartFragments = [@makeCode("#{declare}; #{compare}; #{kvarAssign}#{increment}")] if @returns resultPart = "#{@tab}#{rvar} = [];\n" returnResult = "\n#{@tab}return #{rvar};" body.makeReturn rvar if @guard if body.expressions.length > 1 body.expressions.unshift new If (new Parens @guard).invert(), new Literal "continue" else body = Block.wrap [new If @guard, body] if @guard if @pattern body.expressions.unshift new Assign @name, new Literal "#{svar}[#{kvar}]" defPartFragments = [].concat @makeCode(defPart), @pluckDirectCall(o, body) varPart = "\n#{idt1}#{namePart};" if namePart if @object forPartFragments = [@makeCode("#{kvar} in #{svar}")] guardPart = "\n#{idt1}if (!#{utility 'hasProp', o}.call(#{svar}, #{kvar})) continue;" if @own bodyFragments = body.compileToFragments merge(o, indent: idt1), LEVEL_TOP if bodyFragments and (bodyFragments.length > 0) bodyFragments = [].concat @makeCode("\n"), bodyFragments, @makeCode("\n") [].concat defPartFragments, @makeCode("#{resultPart or ''}#{@tab}for ("), forPartFragments, @makeCode(") {#{guardPart}#{varPart}"), bodyFragments, @makeCode("#{@tab}}#{returnResult or ''}") pluckDirectCall: (o, body) -> defs = [] for expr, idx in body.expressions expr = expr.unwrapAll() continue unless expr instanceof Call val = expr.variable?.unwrapAll() continue unless (val instanceof Code) or (val instanceof Value and val.base?.unwrapAll() instanceof Code and val.properties.length is 1 and val.properties[0].name?.value in ['call', 'apply']) fn = val.base?.unwrapAll() or val ref = new Literal o.scope.freeVariable 'fn' base = new Value ref if val.base [val.base, base] = [base, val] body.expressions[idx] = new Call base, expr.args defs = defs.concat @makeCode(@tab), (new Assign(ref, fn).compileToFragments(o, LEVEL_TOP)), @makeCode(';\n') defs #### Switch # A JavaScript *switch* statement. Converts into a returnable expression on-demand. exports.Switch = class Switch extends Base constructor: (@subject, @cases, @otherwise) -> children: ['subject', 'cases', 'otherwise'] isStatement: YES jumps: (o = {block: yes}) -> for [conds, block] in @cases return jumpNode if jumpNode = block.jumps o @otherwise?.jumps o makeReturn: (res) -> pair[1].makeReturn res for pair in @cases @otherwise or= new Block [new Literal 'void 0'] if res @otherwise?.makeReturn res this compileNode: (o) -> idt1 = o.indent + TAB idt2 = o.indent = idt1 + TAB fragments = [].concat @makeCode(@tab + "switch ("), (if @subject then @subject.compileToFragments(o, LEVEL_PAREN) else @makeCode "false"), @makeCode(") {\n") for [conditions, block], i in @cases for cond in flatten [conditions] cond = cond.invert() unless @subject fragments = fragments.concat @makeCode(idt1 + "case "), cond.compileToFragments(o, LEVEL_PAREN), @makeCode(":\n") fragments = fragments.concat body, @makeCode('\n') if (body = block.compileToFragments o, LEVEL_TOP).length > 0 break if i is @cases.length - 1 and not @otherwise expr = @lastNonComment block.expressions continue if expr instanceof Return or (expr instanceof Literal and expr.jumps() and expr.value isnt 'debugger') fragments.push cond.makeCode(idt2 + 'break;\n') if @otherwise and @otherwise.expressions.length fragments.push @makeCode(idt1 + "default:\n"), (@otherwise.compileToFragments o, LEVEL_TOP)..., @makeCode("\n") fragments.push @makeCode @tab + '}' fragments #### If # *If/else* statements. Acts as an expression by pushing down requested returns # to the last line of each clause. # # Single-expression **Ifs** are compiled into conditional operators if possible, # because ternaries are already proper expressions, and don't need conversion. exports.If = class If extends Base constructor: (condition, @body, options = {}) -> @condition = if options.type is 'unless' then condition.invert() else condition @elseBody = null @isChain = false {@soak} = options children: ['condition', 'body', 'elseBody'] bodyNode: -> @body?.unwrap() elseBodyNode: -> @elseBody?.unwrap() # Rewrite a chain of **Ifs** to add a default case as the final *else*. addElse: (elseBody) -> if @isChain @elseBodyNode().addElse elseBody else @isChain = elseBody instanceof If @elseBody = @ensureBlock elseBody @elseBody.updateLocationDataIfMissing elseBody.locationData this # The **If** only compiles into a statement if either of its bodies needs # to be a statement. Otherwise a conditional operator is safe. isStatement: (o) -> o?.level is LEVEL_TOP or @bodyNode().isStatement(o) or @elseBodyNode()?.isStatement(o) jumps: (o) -> @body.jumps(o) or @elseBody?.jumps(o) compileNode: (o) -> if @isStatement o then @compileStatement o else @compileExpression o makeReturn: (res) -> @elseBody or= new Block [new Literal 'void 0'] if res @body and= new Block [@body.makeReturn res] @elseBody and= new Block [@elseBody.makeReturn res] this ensureBlock: (node) -> if node instanceof Block then node else new Block [node] # Compile the `If` as a regular *if-else* statement. Flattened chains # force inner *else* bodies into statement form. compileStatement: (o) -> child = del o, 'chainChild' exeq = del o, 'isExistentialEquals' if exeq return new If(@condition.invert(), @elseBodyNode(), type: 'if').compileToFragments o indent = o.indent + TAB cond = @condition.compileToFragments o, LEVEL_PAREN body = @ensureBlock(@body).compileToFragments merge o, {indent} ifPart = [].concat @makeCode("if ("), cond, @makeCode(") {\n"), body, @makeCode("\n#{@tab}}") ifPart.unshift @makeCode @tab unless child return ifPart unless @elseBody answer = ifPart.concat @makeCode(' else ') if @isChain o.chainChild = yes answer = answer.concat @elseBody.unwrap().compileToFragments o, LEVEL_TOP else answer = answer.concat @makeCode("{\n"), @elseBody.compileToFragments(merge(o, {indent}), LEVEL_TOP), @makeCode("\n#{@tab}}") answer # Compile the `If` as a conditional operator. compileExpression: (o) -> cond = @condition.compileToFragments o, LEVEL_COND body = @bodyNode().compileToFragments o, LEVEL_LIST alt = if @elseBodyNode() then @elseBodyNode().compileToFragments(o, LEVEL_LIST) else [@makeCode('void 0')] fragments = cond.concat @makeCode(" ? "), body, @makeCode(" : "), alt if o.level >= LEVEL_COND then @wrapInBraces fragments else fragments unfoldSoak: -> @soak and this # Constants # --------- UTILITIES = # Correctly set up a prototype chain for inheritance, including a reference # to the superclass for `super()` calls, and copies of any static properties. extend: (o) -> " function(child, parent) { for (var key in parent) { if (#{utility 'hasProp', o}.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; } " # Create a function bound to the current value of "this". bind: -> ' function(fn, me){ return function(){ return fn.apply(me, arguments); }; } ' # Discover if an item is in an array. 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; } " modulo: -> """ function(a, b) { return (+a % (b = +b) + b) % b; } """ # Shortcuts to speed up the lookup time for native functions. hasProp: -> '{}.hasOwnProperty' slice : -> '[].slice' # Levels indicate a node's position in the AST. Useful for knowing if # parens are necessary or superfluous. LEVEL_TOP = 1 # ...; LEVEL_PAREN = 2 # (...) LEVEL_LIST = 3 # [...] LEVEL_COND = 4 # ... ? x : y LEVEL_OP = 5 # !... LEVEL_ACCESS = 6 # ...[0] # Tabs are two spaces for pretty printing. TAB = ' ' IDENTIFIER = /// ^ (?!\d) [$\w\x7f-\uffff]+ $ /// SIMPLENUM = /^[+-]?\d+$/ HEXNUM = /^[+-]?0x[\da-f]+/i NUMBER = ///^[+-]?(?: 0x[\da-f]+ | # hex \d*\.?\d+ (?:e[+-]?\d+)? # decimal )$///i # Is a literal value a string/regex? IS_STRING = /^['"]/ IS_REGEX = /^\// # Helper Functions # ---------------- # Helper for ensuring that utility functions are assigned at the top level. utility = (name, o) -> {root} = o.scope if name of root.utilities root.utilities[name] else ref = root.freeVariable name root.assign ref, UTILITIES[name] o root.utilities[name] = ref multident = (code, tab) -> code = code.replace /\n/g, '$&' + tab code.replace /\s+$/, '' # Parse a number (+- decimal/hexadecimal) # Examples: 0, -1, 1, 2e3, 2e-3, -0xfe, 0xfe parseNum = (x) -> if not x? 0 else if x.match HEXNUM parseInt x, 16 else parseFloat x isLiteralArguments = (node) -> node instanceof Literal and node.value is 'arguments' and not node.asKey isLiteralThis = (node) -> (node instanceof Literal and node.value is 'this' and not node.asKey) or (node instanceof Code and node.bound) or (node instanceof Call and node.isSuper) isComplexOrAssignable = (node) -> node.isComplex() or node.isAssignable?() # Unfold a node's child if soak, then tuck the node under created `If` unfoldSoak = (o, parent, name) -> return unless ifn = parent[name].unfoldSoak o parent[name] = ifn.body ifn.body = new Value parent ifn 1.9.3~dfsg/src/optparse.coffee0000644000000000000000000000774512531364553015107 0ustar rootroot{repeat} = require './helpers' # A simple **OptionParser** class to parse option flags from the command-line. # Use it like so: # # parser = new OptionParser switches, helpBanner # options = parser.parse process.argv # # The first non-option is considered to be the start of the file (and file # option) list, and all subsequent arguments are left unparsed. exports.OptionParser = class OptionParser # Initialize with a list of valid options, in the form: # # [short-flag, long-flag, description] # # Along with an an optional banner for the usage help. constructor: (rules, @banner) -> @rules = buildRules rules # Parse the list of arguments, populating an `options` object with all of the # specified options, and return it. Options after the first non-option # argument are treated as arguments. `options.arguments` will be an array # containing the remaining arguments. This is a simpler API than many option # parsers that allow you to attach callback actions for every flag. Instead, # you're responsible for interpreting the options object. parse: (args) -> options = arguments: [] skippingArgument = no originalArgs = args args = normalizeArguments args for arg, i in args if skippingArgument skippingArgument = no continue if arg is '--' pos = originalArgs.indexOf '--' options.arguments = options.arguments.concat originalArgs[(pos + 1)..] break isOption = !!(arg.match(LONG_FLAG) or arg.match(SHORT_FLAG)) # the CS option parser is a little odd; options after the first # non-option argument are treated as non-option arguments themselves seenNonOptionArg = options.arguments.length > 0 unless seenNonOptionArg matchedRule = no for rule in @rules if rule.shortFlag is arg or rule.longFlag is arg value = true if rule.hasArgument skippingArgument = yes value = args[i + 1] options[rule.name] = if rule.isList then (options[rule.name] or []).concat value else value matchedRule = yes break throw new Error "unrecognized option: #{arg}" if isOption and not matchedRule if seenNonOptionArg or not isOption options.arguments.push arg options # Return the help text for this **OptionParser**, listing and describing all # of the valid options, for `--help` and such. help: -> lines = [] lines.unshift "#{@banner}\n" if @banner for rule in @rules spaces = 15 - rule.longFlag.length spaces = if spaces > 0 then repeat ' ', spaces else '' letPart = if rule.shortFlag then rule.shortFlag + ', ' else ' ' lines.push ' ' + letPart + rule.longFlag + spaces + rule.description "\n#{ lines.join('\n') }\n" # Helpers # ------- # Regex matchers for option flags. LONG_FLAG = /^(--\w[\w\-]*)/ SHORT_FLAG = /^(-\w)$/ MULTI_FLAG = /^-(\w{2,})/ OPTIONAL = /\[(\w+(\*?))\]/ # Build and return the list of option rules. If the optional *short-flag* is # unspecified, leave it out by padding with `null`. buildRules = (rules) -> for tuple in rules tuple.unshift null if tuple.length < 3 buildRule tuple... # Build a rule from a `-o` short flag, a `--output [DIR]` long flag, and the # description of what the option does. buildRule = (shortFlag, longFlag, description, options = {}) -> match = longFlag.match(OPTIONAL) longFlag = longFlag.match(LONG_FLAG)[1] { name: longFlag.substr 2 shortFlag: shortFlag longFlag: longFlag description: description hasArgument: !!(match and match[1]) isList: !!(match and match[2]) } # Normalize arguments by expanding merged flags into multiple flags. This allows # you to have `-wl` be the same as `--watch --lint`. normalizeArguments = (args) -> args = args[..] result = [] for arg in args if match = arg.match MULTI_FLAG result.push '-' + l for l in match[1].split '' else result.push arg result 1.9.3~dfsg/src/repl.coffee0000644000000000000000000001317012531364553014201 0ustar rootrootfs = require 'fs' path = require 'path' vm = require 'vm' nodeREPL = require 'repl' CoffeeScript = require './coffee-script' {merge, updateSyntaxError} = require './helpers' replDefaults = prompt: 'coffee> ', historyFile: path.join process.env.HOME, '.coffee_history' if process.env.HOME historyMaxInputSize: 10240 eval: (input, context, filename, cb) -> # XXX: multiline hack. input = input.replace /\uFF00/g, '\n' # Node's REPL sends the input ending with a newline and then wrapped in # parens. Unwrap all that. input = input.replace /^\(([\s\S]*)\n\)$/m, '$1' # Require AST nodes to do some AST manipulation. {Block, Assign, Value, Literal} = require './nodes' try # Tokenize the clean input. tokens = CoffeeScript.tokens input # Collect referenced variable names just like in `CoffeeScript.compile`. referencedVars = ( token[1] for token in tokens when token.variable ) # Generate the AST of the tokens. ast = CoffeeScript.nodes tokens # Add assignment to `_` variable to force the input to be an expression. ast = new Block [ new Assign (new Value new Literal '_'), ast, '=' ] js = ast.compile {bare: yes, locals: Object.keys(context), referencedVars} cb null, runInContext js, context, filename catch err # AST's `compile` does not add source code information to syntax errors. updateSyntaxError err, input cb err runInContext = (js, context, filename) -> if context is global vm.runInThisContext js, filename else vm.runInContext js, context, filename addMultilineHandler = (repl) -> {rli, inputStream, outputStream} = repl # Node 0.11.12 changed API, prompt is now _prompt. origPrompt = repl._prompt ? repl.prompt multiline = enabled: off initialPrompt: origPrompt.replace /^[^> ]*/, (x) -> x.replace /./g, '-' prompt: origPrompt.replace /^[^> ]*>?/, (x) -> x.replace /./g, '.' buffer: '' # Proxy node's line listener nodeLineListener = rli.listeners('line')[0] rli.removeListener 'line', nodeLineListener rli.on 'line', (cmd) -> if multiline.enabled multiline.buffer += "#{cmd}\n" rli.setPrompt multiline.prompt rli.prompt true else rli.setPrompt origPrompt nodeLineListener cmd return # Handle Ctrl-v inputStream.on 'keypress', (char, key) -> return unless key and key.ctrl and not key.meta and not key.shift and key.name is 'v' if multiline.enabled # allow arbitrarily switching between modes any time before multiple lines are entered unless multiline.buffer.match /\n/ multiline.enabled = not multiline.enabled rli.setPrompt origPrompt rli.prompt true return # no-op unless the current line is empty return if rli.line? and not rli.line.match /^\s*$/ # eval, print, loop multiline.enabled = not multiline.enabled rli.line = '' rli.cursor = 0 rli.output.cursorTo 0 rli.output.clearLine 1 # XXX: multiline hack multiline.buffer = multiline.buffer.replace /\n/g, '\uFF00' rli.emit 'line', multiline.buffer multiline.buffer = '' else multiline.enabled = not multiline.enabled rli.setPrompt multiline.initialPrompt rli.prompt true return # Store and load command history from a file addHistory = (repl, filename, maxSize) -> lastLine = null try # Get file info and at most maxSize of command history stat = fs.statSync filename size = Math.min maxSize, stat.size # Read last `size` bytes from the file readFd = fs.openSync filename, 'r' buffer = new Buffer(size) fs.readSync readFd, buffer, 0, size, stat.size - size fs.close readFd # Set the history on the interpreter repl.rli.history = buffer.toString().split('\n').reverse() # If the history file was truncated we should pop off a potential partial line repl.rli.history.pop() if stat.size > maxSize # Shift off the final blank newline repl.rli.history.shift() if repl.rli.history[0] is '' repl.rli.historyIndex = -1 lastLine = repl.rli.history[0] fd = fs.openSync filename, 'a' repl.rli.addListener 'line', (code) -> if code and code.length and code isnt '.history' and lastLine isnt code # Save the latest command in the file fs.write fd, "#{code}\n" lastLine = code repl.on 'exit', -> fs.close fd # Add a command to show the history stack repl.commands[getCommandId(repl, 'history')] = help: 'Show command history' action: -> repl.outputStream.write "#{repl.rli.history[..].reverse().join '\n'}\n" repl.displayPrompt() getCommandId = (repl, commandName) -> # Node 0.11 changed API, a command such as '.help' is now stored as 'help' commandsHaveLeadingDot = repl.commands['.help']? if commandsHaveLeadingDot then ".#{commandName}" else commandName module.exports = start: (opts = {}) -> [major, minor, build] = process.versions.node.split('.').map (n) -> parseInt(n) if major is 0 and minor < 8 console.warn "Node 0.8.0+ required for CoffeeScript REPL" process.exit 1 CoffeeScript.register() process.argv = ['coffee'].concat process.argv[2..] opts = merge replDefaults, opts repl = nodeREPL.start opts runInContext opts.prelude, repl.context, 'prelude' if opts.prelude repl.on 'exit', -> repl.outputStream.write '\n' if not repl.rli.closed addMultilineHandler repl addHistory repl, opts.historyFile, opts.historyMaxInputSize if opts.historyFile # Adapt help inherited from the node REPL repl.commands[getCommandId(repl, 'load')].help = 'Load code from a file into this REPL session' repl 1.9.3~dfsg/index.html0000644000000000000000000053452212531364553013305 0ustar rootroot CoffeeScript

CoffeeScript is a little language that compiles into JavaScript. Underneath that awkward Java-esque patina, JavaScript has always had a gorgeous heart. CoffeeScript is an attempt to expose the good parts of JavaScript in a simple way.

The golden rule of CoffeeScript is: "It's just JavaScript". The code compiles one-to-one into the equivalent JS, and there is no interpretation at runtime. You can use any existing JavaScript library seamlessly from CoffeeScript (and vice-versa). The compiled output is readable and pretty-printed, will work in every JavaScript runtime, and tends to run as fast or faster than the equivalent handwritten JavaScript.

Latest Version: 1.9.3

npm install -g coffee-script

Overview

CoffeeScript on the left, compiled JavaScript output on the right.

# Assignment:
number   = 42
opposite = true

# Conditions:
number = -42 if opposite

# Functions:
square = (x) -> x * x

# Arrays:
list = [1, 2, 3, 4, 5]

# Objects:
math =
  root:   Math.sqrt
  square: square
  cube:   (x) -> x * square x

# Splats:
race = (winner, runners...) ->
  print winner, runners

# Existence:
alert "I knew it!" if elvis?

# Array comprehensions:
cubes = (math.cube num for num in list)
var cubes, list, math, num, number, opposite, race, square,
  slice = [].slice;

number = 42;

opposite = true;

if (opposite) {
  number = -42;
}

square = function(x) {
  return x * x;
};

list = [1, 2, 3, 4, 5];

math = {
  root: Math.sqrt,
  square: square,
  cube: function(x) {
    return x * square(x);
  }
};

race = function() {
  var runners, winner;
  winner = arguments[0], runners = 2 <= arguments.length ? slice.call(arguments, 1) : [];
  return print(winner, runners);
};

if (typeof elvis !== "undefined" && elvis !== null) {
  alert("I knew it!");
}

cubes = (function() {
  var i, len, results;
  results = [];
  for (i = 0, len = list.length; i < len; i++) {
    num = list[i];
    results.push(math.cube(num));
  }
  return results;
})();
run: cubes

Installation

The CoffeeScript compiler is itself written in CoffeeScript, using the Jison parser generator. The command-line version of coffee is available as a Node.js utility. The core compiler however, does not depend on Node, and can be run in any JavaScript environment, or in the browser (see "Try CoffeeScript", above).

To install, first make sure you have a working copy of the latest stable version of Node.js. You can then install CoffeeScript globally with npm:

npm install -g coffee-script

When you need CoffeeScript as a dependency, install it locally:

npm install --save coffee-script

If you'd prefer to install the latest master version of CoffeeScript, you can clone the CoffeeScript source repository from GitHub, or download the source directly. To install the latest master CoffeeScript compiler with npm:

npm install -g jashkenas/coffeescript

Or, if you want to install to /usr/local, and don't want to use npm to manage it, open the coffee-script directory and run:

sudo bin/cake install

Usage

Once installed, you should have access to the coffee command, which can execute scripts, compile .coffee files into .js, and provide an interactive REPL. The coffee command takes the following options:

-c, --compile Compile a .coffee script into a .js JavaScript file of the same name.
-m, --map Generate source maps alongside the compiled JavaScript files. Adds sourceMappingURL directives to the JavaScript as well.
-i, --interactive Launch an interactive CoffeeScript session to try short snippets. Identical to calling coffee with no arguments.
-o, --output [DIR] Write out all compiled JavaScript files into the specified directory. Use in conjunction with --compile or --watch.
-j, --join [FILE] Before compiling, concatenate all scripts together in the order they were passed, and write them into the specified file. Useful for building large projects.
-w, --watch Watch files for changes, rerunning the specified command when any file is updated.
-p, --print Instead of writing out the JavaScript as a file, print it directly to stdout.
-s, --stdio Pipe in CoffeeScript to STDIN and get back JavaScript over STDOUT. Good for use with processes written in other languages. An example:
cat src/cake.coffee | coffee -sc
-l, --literate Parses the code as Literate CoffeeScript. You only need to specify this when passing in code directly over stdio, or using some sort of extension-less file name.
-e, --eval Compile and print a little snippet of CoffeeScript directly from the command line. For example:
coffee -e "console.log num for num in [10..1]"
-b, --bare Compile the JavaScript without the top-level function safety wrapper.
-t, --tokens Instead of parsing the CoffeeScript, just lex it, and print out the token stream: [IDENTIFIER square] [ASSIGN =] [PARAM_START (] ...
-n, --nodes Instead of compiling the CoffeeScript, just lex and parse it, and print out the parse tree:
Expressions
  Assign
    Value "square"
    Code "x"
      Op *
        Value "x"
        Value "x"
--nodejs The node executable has some useful options you can set, such as
--debug, --debug-brk, --max-stack-size, and --expose-gc. Use this flag to forward options directly to Node.js. To pass multiple flags, use --nodejs multiple times.

Examples:

  • Compile a directory tree of .coffee files in src into a parallel tree of .js files in lib:
    coffee --compile --output lib/ src/
  • Watch a file for changes, and recompile it every time the file is saved:
    coffee --watch --compile experimental.coffee
  • Concatenate a list of files into a single script:
    coffee --join project.js --compile src/*.coffee
  • Print out the compiled JS from a one-liner:
    coffee -bpe "alert i for i in [0..10]"
  • All together now, watch and recompile an entire project as you work on it:
    coffee -o lib/ -cw src/
  • Start the CoffeeScript REPL (Ctrl-D to exit, Ctrl-Vfor multi-line):
    coffee

Literate CoffeeScript

Besides being used as an ordinary programming language, CoffeeScript may also be written in "literate" mode. If you name your file with a .litcoffee extension, you can write it as a Markdown document — a document that also happens to be executable CoffeeScript code. The compiler will treat any indented blocks (Markdown's way of indicating source code) as code, and ignore the rest as comments.

Just for kicks, a little bit of the compiler is currently implemented in this fashion: See it as a document, raw, and properly highlighted in a text editor.

I'm fairly excited about this direction for the language, and am looking forward to writing (and more importantly, reading) more programs in this style. More information about Literate CoffeeScript, including an example program, are available in this blog post.

Language Reference

This reference is structured so that it can be read from top to bottom, if you like. Later sections use ideas and syntax previously introduced. Familiarity with JavaScript is assumed. In all of the following examples, the source CoffeeScript is provided on the left, and the direct compilation into JavaScript is on the right.

Many of the examples can be run (where it makes sense) by pressing the run button on the right, and can be loaded into the "Try CoffeeScript" console by pressing the load button on the left.

First, the basics: CoffeeScript uses significant whitespace to delimit blocks of code. You don't need to use semicolons ; to terminate expressions, ending the line will do just as well (although semicolons can still be used to fit multiple expressions onto a single line). Instead of using curly braces { } to surround blocks of code in functions, if-statements, switch, and try/catch, use indentation.

You don't need to use parentheses to invoke a function if you're passing arguments. The implicit call wraps forward to the end of the line or block expression.
console.log sys.inspect objectconsole.log(sys.inspect(object));

Functions Functions are defined by an optional list of parameters in parentheses, an arrow, and the function body. The empty function looks like this: ->

square = (x) -> x * x
cube   = (x) -> square(x) * x
var cube, square;

square = function(x) {
  return x * x;
};

cube = function(x) {
  return square(x) * x;
};
load
run: cube(5)

Functions may also have default values for arguments, which will be used if the incoming argument is missing (null or undefined).

fill = (container, liquid = "coffee") ->
  "Filling the #{container} with #{liquid}..."






var fill;

fill = function(container, liquid) {
  if (liquid == null) {
    liquid = "coffee";
  }
  return "Filling the " + container + " with " + liquid + "...";
};
load
run: fill("cup")

Objects and Arrays The CoffeeScript literals for objects and arrays look very similar to their JavaScript cousins. When each property is listed on its own line, the commas are optional. Objects may be created using indentation instead of explicit braces, similar to YAML.

song = ["do", "re", "mi", "fa", "so"]

singers = {Jagger: "Rock", Elvis: "Roll"}

bitlist = [
  1, 0, 1
  0, 0, 1
  1, 1, 0
]

kids =
  brother:
    name: "Max"
    age:  11
  sister:
    name: "Ida"
    age:  9


var bitlist, kids, singers, song;

song = ["do", "re", "mi", "fa", "so"];

singers = {
  Jagger: "Rock",
  Elvis: "Roll"
};

bitlist = [1, 0, 1, 0, 0, 1, 1, 1, 0];

kids = {
  brother: {
    name: "Max",
    age: 11
  },
  sister: {
    name: "Ida",
    age: 9
  }
};
load
run: song.join(" ... ")

In JavaScript, you can't use reserved words, like class, as properties of an object, without quoting them as strings. CoffeeScript notices reserved words used as keys in objects and quotes them for you, so you don't have to worry about it (say, when using jQuery).

$('.account').attr class: 'active'

log object.class


$('.account').attr({
  "class": 'active'
});

log(object["class"]);
load

Lexical Scoping and Variable Safety The CoffeeScript compiler takes care to make sure that all of your variables are properly declared within lexical scope — you never need to write var yourself.

outer = 1
changeNumbers = ->
  inner = -1
  outer = 10
inner = changeNumbers()
var changeNumbers, inner, outer;

outer = 1;

changeNumbers = function() {
  var inner;
  inner = -1;
  return outer = 10;
};

inner = changeNumbers();
load
run: inner

Notice how all of the variable declarations have been pushed up to the top of the closest scope, the first time they appear. outer is not redeclared within the inner function, because it's already in scope; inner within the function, on the other hand, should not be able to change the value of the external variable of the same name, and therefore has a declaration of its own.

This behavior is effectively identical to Ruby's scope for local variables. Because you don't have direct access to the var keyword, it's impossible to shadow an outer variable on purpose, you may only refer to it. So be careful that you're not reusing the name of an external variable accidentally, if you're writing a deeply nested function.

Although suppressed within this documentation for clarity, all CoffeeScript output is wrapped in an anonymous function: (function(){ ... })(); This safety wrapper, combined with the automatic generation of the var keyword, make it exceedingly difficult to pollute the global namespace by accident.

If you'd like to create top-level variables for other scripts to use, attach them as properties on window, or on the exports object in CommonJS. The existential operator (covered below), gives you a reliable way to figure out where to add them; if you're targeting both CommonJS and the browser: exports ? this

If, Else, Unless, and Conditional Assignment If/else statements can be written without the use of parentheses and curly brackets. As with functions and other block expressions, multi-line conditionals are delimited by indentation. There's also a handy postfix form, with the if or unless at the end.

CoffeeScript can compile if statements into JavaScript expressions, using the ternary operator when possible, and closure wrapping otherwise. There is no explicit ternary statement in CoffeeScript — you simply use a regular if statement on a single line.

mood = greatlyImproved if singing

if happy and knowsIt
  clapsHands()
  chaChaCha()
else
  showIt()

date = if friday then sue else jill



var date, mood;

if (singing) {
  mood = greatlyImproved;
}

if (happy && knowsIt) {
  clapsHands();
  chaChaCha();
} else {
  showIt();
}

date = friday ? sue : jill;
load

Splats... The JavaScript arguments object is a useful way to work with functions that accept variable numbers of arguments. CoffeeScript provides splats ..., both for function definition as well as invocation, making variable numbers of arguments a little bit more palatable.

gold = silver = rest = "unknown"

awardMedals = (first, second, others...) ->
  gold   = first
  silver = second
  rest   = others

contenders = [
  "Michael Phelps"
  "Liu Xiang"
  "Yao Ming"
  "Allyson Felix"
  "Shawn Johnson"
  "Roman Sebrle"
  "Guo Jingjing"
  "Tyson Gay"
  "Asafa Powell"
  "Usain Bolt"
]

awardMedals contenders...

alert "Gold: " + gold
alert "Silver: " + silver
alert "The Field: " + rest


var awardMedals, contenders, gold, rest, silver,
  slice = [].slice;

gold = silver = rest = "unknown";

awardMedals = function() {
  var first, others, second;
  first = arguments[0], second = arguments[1], others = 3 <= arguments.length ? slice.call(arguments, 2) : [];
  gold = first;
  silver = second;
  return rest = others;
};

contenders = ["Michael Phelps", "Liu Xiang", "Yao Ming", "Allyson Felix", "Shawn Johnson", "Roman Sebrle", "Guo Jingjing", "Tyson Gay", "Asafa Powell", "Usain Bolt"];

awardMedals.apply(null, contenders);

alert("Gold: " + gold);

alert("Silver: " + silver);

alert("The Field: " + rest);
load
run

Loops and Comprehensions Most of the loops you'll write in CoffeeScript will be comprehensions over arrays, objects, and ranges. Comprehensions replace (and compile into) for loops, with optional guard clauses and the value of the current array index. Unlike for loops, array comprehensions are expressions, and can be returned and assigned.

# Eat lunch.
eat food for food in ['toast', 'cheese', 'wine']

# Fine five course dining.
courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']
menu i + 1, dish for dish, i in courses

# Health conscious meal.
foods = ['broccoli', 'spinach', 'chocolate']
eat food for food in foods when food isnt 'chocolate'
var courses, dish, food, foods, i, j, k, l, len, len1, len2, ref;

ref = ['toast', 'cheese', 'wine'];
for (j = 0, len = ref.length; j < len; j++) {
  food = ref[j];
  eat(food);
}

courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'];

for (i = k = 0, len1 = courses.length; k < len1; i = ++k) {
  dish = courses[i];
  menu(i + 1, dish);
}

foods = ['broccoli', 'spinach', 'chocolate'];

for (l = 0, len2 = foods.length; l < len2; l++) {
  food = foods[l];
  if (food !== 'chocolate') {
    eat(food);
  }
}
load

Comprehensions should be able to handle most places where you otherwise would use a loop, each/forEach, map, or select/filter, for example: shortNames = (name for name in list when name.length < 5)
If you know the start and end of your loop, or would like to step through in fixed-size increments, you can use a range to specify the start and end of your comprehension.

countdown = (num for num in [10..1])

var countdown, num;

countdown = (function() {
  var i, results;
  results = [];
  for (num = i = 10; i >= 1; num = --i) {
    results.push(num);
  }
  return results;
})();
load
run: countdown

Note how because we are assigning the value of the comprehensions to a variable in the example above, CoffeeScript is collecting the result of each iteration into an array. Sometimes functions end with loops that are intended to run only for their side-effects. Be careful that you're not accidentally returning the results of the comprehension in these cases, by adding a meaningful return value — like true — or null, to the bottom of your function.

To step through a range comprehension in fixed-size chunks, use by, for example:
evens = (x for x in [0..10] by 2)

If you don't need the current iteration value you may omit it:
browser.closeCurrentTab() for [0...count]

Comprehensions can also be used to iterate over the keys and values in an object. Use of to signal comprehension over the properties of an object instead of the values in an array.

yearsOld = max: 10, ida: 9, tim: 11

ages = for child, age of yearsOld
  "#{child} is #{age}"
var age, ages, child, yearsOld;

yearsOld = {
  max: 10,
  ida: 9,
  tim: 11
};

ages = (function() {
  var results;
  results = [];
  for (child in yearsOld) {
    age = yearsOld[child];
    results.push(child + " is " + age);
  }
  return results;
})();
load
run: ages.join(", ")

If you would like to iterate over just the keys that are defined on the object itself, by adding a hasOwnProperty check to avoid properties that may be inherited from the prototype, use
for own key, value of object

The only low-level loop that CoffeeScript provides is the while loop. The main difference from JavaScript is that the while loop can be used as an expression, returning an array containing the result of each iteration through the loop.

# Econ 101
if this.studyingEconomics
  buy()  while supply > demand
  sell() until supply > demand

# Nursery Rhyme
num = 6
lyrics = while num -= 1
  "#{num} little monkeys, jumping on the bed.
    One fell out and bumped his head."
var lyrics, num;

if (this.studyingEconomics) {
  while (supply > demand) {
    buy();
  }
  while (!(supply > demand)) {
    sell();
  }
}

num = 6;

lyrics = (function() {
  var results;
  results = [];
  while (num -= 1) {
    results.push(num + " little monkeys, jumping on the bed. One fell out and bumped his head.");
  }
  return results;
})();
load
run: lyrics.join(" ")

For readability, the until keyword is equivalent to while not, and the loop keyword is equivalent to while true.

When using a JavaScript loop to generate functions, it's common to insert a closure wrapper in order to ensure that loop variables are closed over, and all the generated functions don't just share the final values. CoffeeScript provides the do keyword, which immediately invokes a passed function, forwarding any arguments.

for filename in list
  do (filename) ->
    fs.readFile filename, (err, contents) ->
      compile filename, contents.toString()
var filename, fn, i, len;

fn = function(filename) {
  return fs.readFile(filename, function(err, contents) {
    return compile(filename, contents.toString());
  });
};
for (i = 0, len = list.length; i < len; i++) {
  filename = list[i];
  fn(filename);
}
load

Array Slicing and Splicing with Ranges Ranges can also be used to extract slices of arrays. With two dots (3..6), the range is inclusive (3, 4, 5, 6); with three dots (3...6), the range excludes the end (3, 4, 5). Slices indices have useful defaults. An omitted first index defaults to zero and an omitted second index defaults to the size of the array.

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]

start   = numbers[0..2]

middle  = numbers[3...-2]

end     = numbers[-2..]

copy    = numbers[..]
var copy, end, middle, numbers, start;

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];

start = numbers.slice(0, 3);

middle = numbers.slice(3, -2);

end = numbers.slice(-2);

copy = numbers.slice(0);
load
run: middle

The same syntax can be used with assignment to replace a segment of an array with new values, splicing it.

numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

numbers[3..6] = [-3, -4, -5, -6]



 
var numbers, ref;

numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

[].splice.apply(numbers, [3, 4].concat(ref = [-3, -4, -5, -6])), ref;
load
run: numbers

Note that JavaScript strings are immutable, and can't be spliced.

Everything is an Expression (at least, as much as possible) You might have noticed how even though we don't add return statements to CoffeeScript functions, they nonetheless return their final value. The CoffeeScript compiler tries to make sure that all statements in the language can be used as expressions. Watch how the return gets pushed down into each possible branch of execution in the function below.

grade = (student) ->
  if student.excellentWork
    "A+"
  else if student.okayStuff
    if student.triedHard then "B" else "B-"
  else
    "C"

eldest = if 24 > 21 then "Liz" else "Ike"
var eldest, grade;

grade = function(student) {
  if (student.excellentWork) {
    return "A+";
  } else if (student.okayStuff) {
    if (student.triedHard) {
      return "B";
    } else {
      return "B-";
    }
  } else {
    return "C";
  }
};

eldest = 24 > 21 ? "Liz" : "Ike";
load
run: eldest

Even though functions will always return their final value, it's both possible and encouraged to return early from a function body writing out the explicit return (return value), when you know that you're done.

Because variable declarations occur at the top of scope, assignment can be used within expressions, even for variables that haven't been seen before:

six = (one = 1) + (two = 2) + (three = 3)


var one, six, three, two;

six = (one = 1) + (two = 2) + (three = 3);
load
run: six

Things that would otherwise be statements in JavaScript, when used as part of an expression in CoffeeScript, are converted into expressions by wrapping them in a closure. This lets you do useful things, like assign the result of a comprehension to a variable:

# The first ten global properties.

globals = (name for name of window)[0...10]
var globals, name;

globals = ((function() {
  var results;
  results = [];
  for (name in window) {
    results.push(name);
  }
  return results;
})()).slice(0, 10);
load
run: globals

As well as silly things, like passing a try/catch statement directly into a function call:

alert(
  try
    nonexistent / undefined
  catch error
    "And the error is ... #{error}"
)

var error;

alert((function() {
  try {
    return nonexistent / void 0;
  } catch (_error) {
    error = _error;
    return "And the error is ... " + error;
  }
})());
load
run

There are a handful of statements in JavaScript that can't be meaningfully converted into expressions, namely break, continue, and return. If you make use of them within a block of code, CoffeeScript won't try to perform the conversion.

Operators and Aliases Because the == operator frequently causes undesirable coercion, is intransitive, and has a different meaning than in other languages, CoffeeScript compiles == into ===, and != into !==. In addition, is compiles into ===, and isnt into !==.

You can use not as an alias for !.

For logic, and compiles to &&, and or into ||.

Instead of a newline or semicolon, then can be used to separate conditions from expressions, in while, if/else, and switch/when statements.

As in YAML, on and yes are the same as boolean true, while off and no are boolean false.

unless can be used as the inverse of if.

As a shortcut for this.property, you can use @property.

You can use in to test for array presence, and of to test for JavaScript object-key presence.

To simplify math expressions, ** can be used for exponentiation and // performs integer division. % works just like in JavaScript, while %% provides “dividend dependent modulo”:

-7 % 5 == -2 # The remainder of 7 / 5
-7 %% 5 == 3 # n %% 5 is always between 0 and 4

tabs.selectTabAtIndex((tabs.currentIndex - count) %% tabs.length)
var modulo = function(a, b) { return (+a % (b = +b) + b) % b; };

-7 % 5 === -2;

modulo(-7, 5) === 3;

tabs.selectTabAtIndex(modulo(tabs.currentIndex - count, tabs.length));
load

All together now:

CoffeeScriptJavaScript
is===
isnt!==
not!
and&&
or||
true, yes, ontrue
false, no, offfalse
@, thisthis
ofin
inno JS equivalent
a ** bMath.pow(a, b)
a // bMath.floor(a / b)
a %% b(a % b + b) % b
launch() if ignition is on

volume = 10 if band isnt SpinalTap

letTheWildRumpusBegin() unless answer is no

if car.speed < limit then accelerate()

winner = yes if pick in [47, 92, 13]

print inspect "My name is #{@name}"
var volume, winner;

if (ignition === true) {
  launch();
}

if (band !== SpinalTap) {
  volume = 10;
}

if (answer !== false) {
  letTheWildRumpusBegin();
}

if (car.speed < limit) {
  accelerate();
}

if (pick === 47 || pick === 92 || pick === 13) {
  winner = true;
}

print(inspect("My name is " + this.name));
load

The Existential Operator It's a little difficult to check for the existence of a variable in JavaScript. if (variable) ... comes close, but fails for zero, the empty string, and false. CoffeeScript's existential operator ? returns true unless a variable is null or undefined, which makes it analogous to Ruby's nil?

It can also be used for safer conditional assignment than ||= provides, for cases where you may be handling numbers or strings.

solipsism = true if mind? and not world?

speed = 0
speed ?= 15

footprints = yeti ? "bear"






 
var footprints, solipsism, speed;

if ((typeof mind !== "undefined" && mind !== null) && (typeof world === "undefined" || world === null)) {
  solipsism = true;
}

speed = 0;

if (speed == null) {
  speed = 15;
}

footprints = typeof yeti !== "undefined" && yeti !== null ? yeti : "bear";
load
run: footprints

The accessor variant of the existential operator ?. can be used to soak up null references in a chain of properties. Use it instead of the dot accessor . in cases where the base value may be null or undefined. If all of the properties exist then you'll get the expected result, if the chain is broken, undefined is returned instead of the TypeError that would be raised otherwise.

zip = lottery.drawWinner?().address?.zipcode
var ref, zip;

zip = typeof lottery.drawWinner === "function" ? (ref = lottery.drawWinner().address) != null ? ref.zipcode : void 0 : void 0;
load

Soaking up nulls is similar to Ruby's andand gem, and to the safe navigation operator in Groovy.

Classes, Inheritance, and Super JavaScript's prototypal inheritance has always been a bit of a brain-bender, with a whole family tree of libraries that provide a cleaner syntax for classical inheritance on top of JavaScript's prototypes: Base2, Prototype.js, JS.Class, etc. The libraries provide syntactic sugar, but the built-in inheritance would be completely usable if it weren't for a couple of small exceptions: it's awkward to call super (the prototype object's implementation of the current function), and it's awkward to correctly set the prototype chain.

Instead of repetitively attaching functions to a prototype, CoffeeScript provides a basic class structure that allows you to name your class, set the superclass, assign prototypal properties, and define the constructor, in a single assignable expression.

Constructor functions are named, to better support helpful stack traces. In the first class in the example below, this.constructor.name is "Animal".

class Animal
  constructor: (@name) ->

  move: (meters) ->
    alert @name + " moved #{meters}m."

class Snake extends Animal
  move: ->
    alert "Slithering..."
    super 5

class Horse extends Animal
  move: ->
    alert "Galloping..."
    super 45

sam = new Snake "Sammy the Python"
tom = new Horse "Tommy the Palomino"

sam.move()
tom.move()




var Animal, Horse, Snake, sam, tom,
  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;

Animal = (function() {
  function Animal(name) {
    this.name = name;
  }

  Animal.prototype.move = function(meters) {
    return alert(this.name + (" moved " + meters + "m."));
  };

  return Animal;

})();

Snake = (function(superClass) {
  extend(Snake, superClass);

  function Snake() {
    return Snake.__super__.constructor.apply(this, arguments);
  }

  Snake.prototype.move = function() {
    alert("Slithering...");
    return Snake.__super__.move.call(this, 5);
  };

  return Snake;

})(Animal);

Horse = (function(superClass) {
  extend(Horse, superClass);

  function Horse() {
    return Horse.__super__.constructor.apply(this, arguments);
  }

  Horse.prototype.move = function() {
    alert("Galloping...");
    return Horse.__super__.move.call(this, 45);
  };

  return Horse;

})(Animal);

sam = new Snake("Sammy the Python");

tom = new Horse("Tommy the Palomino");

sam.move();

tom.move();
load
run

If structuring your prototypes classically isn't your cup of tea, CoffeeScript provides a couple of lower-level conveniences. The extends operator helps with proper prototype setup, and can be used to create an inheritance chain between any pair of constructor functions; :: gives you quick access to an object's prototype; and super() is converted into a call against the immediate ancestor's method of the same name.

String::dasherize = ->
  this.replace /_/g, "-"

String.prototype.dasherize = function() {
  return this.replace(/_/g, "-");
};
load
run: "one_two".dasherize()

Finally, class definitions are blocks of executable code, which make for interesting metaprogramming possibilities. Because in the context of a class definition, this is the class object itself (the constructor function), you can assign static properties by using
@property: value, and call functions defined in parent classes: @attr 'title', type: 'text'

Destructuring Assignment To make extracting values from complex arrays and objects more convenient, CoffeeScript implements ECMAScript Harmony's proposed destructuring assignment syntax. When you assign an array or object literal to a value, CoffeeScript breaks up and matches both sides against each other, assigning the values on the right to the variables on the left. In the simplest case, it can be used for parallel assignment:

theBait   = 1000
theSwitch = 0

[theBait, theSwitch] = [theSwitch, theBait]




 
var ref, theBait, theSwitch;

theBait = 1000;

theSwitch = 0;

ref = [theSwitch, theBait], theBait = ref[0], theSwitch = ref[1];
load
run: theBait

But it's also helpful for dealing with functions that return multiple values.

weatherReport = (location) ->
  # Make an Ajax request to fetch the weather...
  [location, 72, "Mostly Sunny"]

[city, temp, forecast] = weatherReport "Berkeley, CA"




var city, forecast, ref, temp, weatherReport;

weatherReport = function(location) {
  return [location, 72, "Mostly Sunny"];
};

ref = weatherReport("Berkeley, CA"), city = ref[0], temp = ref[1], forecast = ref[2];
load
run: forecast

Destructuring assignment can be used with any depth of array and object nesting, to help pull out deeply nested properties.

futurists =
  sculptor: "Umberto Boccioni"
  painter:  "Vladimir Burliuk"
  poet:
    name:   "F.T. Marinetti"
    address: [
      "Via Roma 42R"
      "Bellagio, Italy 22021"
    ]

{poet: {name, address: [street, city]}} = futurists



var city, futurists, name, ref, ref1, street;

futurists = {
  sculptor: "Umberto Boccioni",
  painter: "Vladimir Burliuk",
  poet: {
    name: "F.T. Marinetti",
    address: ["Via Roma 42R", "Bellagio, Italy 22021"]
  }
};

ref = futurists.poet, name = ref.name, (ref1 = ref.address, street = ref1[0], city = ref1[1]);
load
run: name + "-" + street

Destructuring assignment can even be combined with splats.

tag = "<impossible>"

[open, contents..., close] = tag.split("")






var close, contents, i, open, ref, tag,
  slice = [].slice;

tag = "<impossible>";

ref = tag.split(""), open = ref[0], contents = 3 <= ref.length ? slice.call(ref, 1, i = ref.length - 1) : (i = 1, []), close = ref[i++];
load
run: contents.join("")

Expansion can be used to retrieve elements from the end of an array without having to assign the rest of its values. It works in function parameter lists as well.

text = "Every literary critic believes he will
        outwit history and have the last word"

[first, ..., last] = text.split " "



var first, last, ref, text;

text = "Every literary critic believes he will outwit history and have the last word";

ref = text.split(" "), first = ref[0], last = ref[ref.length - 1];
load
run: first + " " + last

Destructuring assignment is also useful when combined with class constructors to assign properties to your instance from an options object passed to the constructor.

class Person
  constructor: (options) -> 
    {@name, @age, @height} = options

tim = new Person age: 4

var Person, tim;

Person = (function() {
  function Person(options) {
    this.name = options.name, this.age = options.age, this.height = options.height;
  }

  return Person;

})();

tim = new Person({
  age: 4
});
load
run: tim.age

Bound Functions, Generator Functions In JavaScript, the this keyword is dynamically scoped to mean the object that the current function is attached to. If you pass a function as a callback or attach it to a different object, the original value of this will be lost. If you're not familiar with this behavior, this Digital Web article gives a good overview of the quirks.

The fat arrow => can be used to both define a function, and to bind it to the current value of this, right on the spot. This is helpful when using callback-based libraries like Prototype or jQuery, for creating iterator functions to pass to each, or event-handler functions to use with on. Functions created with the fat arrow are able to access properties of the this where they're defined.

Account = (customer, cart) ->
  @customer = customer
  @cart = cart

  $('.shopping_cart').on 'click', (event) =>
    @customer.purchase @cart
var Account;

Account = function(customer, cart) {
  this.customer = customer;
  this.cart = cart;
  return $('.shopping_cart').on('click', (function(_this) {
    return function(event) {
      return _this.customer.purchase(_this.cart);
    };
  })(this));
};
load

If we had used -> in the callback above, @customer would have referred to the undefined "customer" property of the DOM element, and trying to call purchase() on it would have raised an exception.

When used in a class definition, methods declared with the fat arrow will be automatically bound to each instance of the class when the instance is constructed.

CoffeeScript functions also support ES6 generator functions through the yield keyword. There's no function*(){} nonsense — a generator in CoffeeScript is simply a function that yields.

perfectSquares = ->
  num = 0
  loop
    num += 1
    yield num * num
  return

window.ps or= perfectSquares()
var perfectSquares;

perfectSquares = function*() {
  var num;
  num = 0;
  while (true) {
    num += 1;
    (yield num * num);
  }
};

window.ps || (window.ps = perfectSquares());
load
run: ps.next().value

yield* is called yield from, and yield return may be used if you need to force a generator that doesn't yield.

Embedded JavaScript Hopefully, you'll never need to use it, but if you ever need to intersperse snippets of JavaScript within your CoffeeScript, you can use backticks to pass it straight through.

hi = `function() {
  return [document.title, "Hello JavaScript"].join(": ");
}`



var hi;

hi = function() {
  return [document.title, "Hello JavaScript"].join(": ");
};
load
run: hi()

Switch/When/Else Switch statements in JavaScript are a bit awkward. You need to remember to break at the end of every case statement to avoid accidentally falling through to the default case. CoffeeScript prevents accidental fall-through, and can convert the switch into a returnable, assignable expression. The format is: switch condition, when clauses, else the default case.

As in Ruby, switch statements in CoffeeScript can take multiple values for each when clause. If any of the values match, the clause runs.

switch day
  when "Mon" then go work
  when "Tue" then go relax
  when "Thu" then go iceFishing
  when "Fri", "Sat"
    if day is bingoDay
      go bingo
      go dancing
  when "Sun" then go church
  else go work
switch (day) {
  case "Mon":
    go(work);
    break;
  case "Tue":
    go(relax);
    break;
  case "Thu":
    go(iceFishing);
    break;
  case "Fri":
  case "Sat":
    if (day === bingoDay) {
      go(bingo);
      go(dancing);
    }
    break;
  case "Sun":
    go(church);
    break;
  default:
    go(work);
}
load

Switch statements can also be used without a control expression, turning them in to a cleaner alternative to if/else chains.

score = 76
grade = switch
  when score < 60 then 'F'
  when score < 70 then 'D'
  when score < 80 then 'C'
  when score < 90 then 'B'
  else 'A'
# grade == 'C'
var grade, score;

score = 76;

grade = (function() {
  switch (false) {
    case !(score < 60):
      return 'F';
    case !(score < 70):
      return 'D';
    case !(score < 80):
      return 'C';
    case !(score < 90):
      return 'B';
    default:
      return 'A';
  }
})();
load

Try/Catch/Finally Try-expressions have the same semantics as try-statements in JavaScript, though in CoffeeScript, you may omit both the catch and finally parts. The catch part may also omit the error parameter if it is not needed.

try
  allHellBreaksLoose()
  catsAndDogsLivingTogether()
catch error
  print error
finally
  cleanUp()

var error;

try {
  allHellBreaksLoose();
  catsAndDogsLivingTogether();
} catch (_error) {
  error = _error;
  print(error);
} finally {
  cleanUp();
}
load

Chained Comparisons CoffeeScript borrows chained comparisons from Python — making it easy to test if a value falls within a certain range.

cholesterol = 127

healthy = 200 > cholesterol > 60


var cholesterol, healthy;

cholesterol = 127;

healthy = (200 > cholesterol && cholesterol > 60);
load
run: healthy

String Interpolation, Block Strings, and Block Comments Ruby-style string interpolation is included in CoffeeScript. Double-quoted strings allow for interpolated values, using #{ ... }, and single-quoted strings are literal. You may even use interpolation in object keys.

author = "Wittgenstein"
quote  = "A picture is a fact. -- #{ author }"

sentence = "#{ 22 / 7 } is a decent approximation of π"




var author, quote, sentence;

author = "Wittgenstein";

quote = "A picture is a fact. -- " + author;

sentence = (22 / 7) + " is a decent approximation of π";
load
run: sentence

Multiline strings are allowed in CoffeeScript. Lines are joined by a single space unless they end with a backslash. Indentation is ignored.

mobyDick = "Call me Ishmael. Some years ago --
  never mind how long precisely -- having little
  or no money in my purse, and nothing particular
  to interest me on shore, I thought I would sail
  about a little and see the watery part of the
  world..."


var mobyDick;

mobyDick = "Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...";
load
run: mobyDick

Block strings can be used to hold formatted or indentation-sensitive text (or, if you just don't feel like escaping quotes and apostrophes). The indentation level that begins the block is maintained throughout, so you can keep it all aligned with the body of your code.

html = """
       <strong>
         cup of coffeescript
       </strong>
       """
       
var html;

html = "<strong>\n  cup of coffeescript\n</strong>";
load
run: html

Double-quoted block strings, like other double-quoted strings, allow interpolation.

Sometimes you'd like to pass a block comment through to the generated JavaScript. For example, when you need to embed a licensing header at the top of a file. Block comments, which mirror the syntax for block strings, are preserved in the generated code.

###
SkinnyMochaHalfCaffScript Compiler v1.0
Released under the MIT License
###



/*
SkinnyMochaHalfCaffScript Compiler v1.0
Released under the MIT License
 */

load

Block Regular Expressions Similar to block strings and comments, CoffeeScript supports block regexes — extended regular expressions that ignore internal whitespace and can contain comments and interpolation. Modeled after Perl's /x modifier, CoffeeScript's block regexes are delimited by /// and go a long way towards making complex regular expressions readable. To quote from the CoffeeScript source:

OPERATOR = /// ^ (
  ?: [-=]>             # function
   | [-+*/%<>&|^!?=]=  # compound assign / compare
   | >>>=?             # zero-fill right shift
   | ([-+:])\1         # doubles
   | ([&|<>])\2=?      # logic / shift
   | \?\.              # soak access
   | \.{2,3}           # range or splat
) ///


var OPERATOR;

OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
load

Cake, and Cakefiles

CoffeeScript includes a (very) simple build system similar to Make and Rake. Naturally, it's called Cake, and is used for the tasks that build and test the CoffeeScript language itself. Tasks are defined in a file named Cakefile, and can be invoked by running cake [task] from within the directory. To print a list of all the tasks and options, just type cake.

Task definitions are written in CoffeeScript, so you can put arbitrary code in your Cakefile. Define a task with a name, a long description, and the function to invoke when the task is run. If your task takes a command-line option, you can define the option with short and long flags, and it will be made available in the options object. Here's a task that uses the Node.js API to rebuild CoffeeScript's parser:

fs = require 'fs'

option '-o', '--output [DIR]', 'directory for compiled code'

task 'build:parser', 'rebuild the Jison parser', (options) ->
  require 'jison'
  code = require('./lib/grammar').parser.generate()
  dir  = options.output or 'lib'
  fs.writeFile "#{dir}/parser.js", code
var fs;

fs = require('fs');

option('-o', '--output [DIR]', 'directory for compiled code');

task('build:parser', 'rebuild the Jison parser', function(options) {
  var code, dir;
  require('jison');
  code = require('./lib/grammar').parser.generate();
  dir = options.output || 'lib';
  return fs.writeFile(dir + "/parser.js", code);
});
load

If you need to invoke one task before another — for example, running build before test, you can use the invoke function: invoke 'build'. Cake tasks are a minimal way to expose your CoffeeScript functions to the command line, so don't expect any fanciness built-in. If you need dependencies, or async callbacks, it's best to put them in your code itself — not the cake task.

Source Maps

CoffeeScript 1.6.1 and above include support for generating source maps, a way to tell your JavaScript engine what part of your CoffeeScript program matches up with the code being evaluated. Browsers that support it can automatically use source maps to show your original source code in the debugger. To generate source maps alongside your JavaScript files, pass the --map or -m flag to the compiler.

For a full introduction to source maps, how they work, and how to hook them up in your browser, read the HTML5 Tutorial.

"text/coffeescript" Script Tags

While it's not recommended for serious use, CoffeeScripts may be included directly within the browser using <script type="text/coffeescript"> tags. The source includes a compressed and minified version of the compiler (Download current version here, 39k when gzipped) as extras/coffee-script.js. Include this file on a page with inline CoffeeScript tags, and it will compile and evaluate them in order.

In fact, the little bit of glue script that runs "Try CoffeeScript" above, as well as the jQuery for the menu, is implemented in just this way. View source and look at the bottom of the page to see the example. Including the script also gives you access to CoffeeScript.compile() so you can pop open Firebug and try compiling some strings.

The usual caveats about CoffeeScript apply — your inline scripts will run within a closure wrapper, so if you want to expose global variables or functions, attach them to the window object.

Books

There are a number of excellent resources to help you get started with CoffeeScript, some of which are freely available online.

Screencasts

  • A Sip of CoffeeScript is a Code School Course which combines 6 screencasts with in-browser coding to make learning fun. The first level is free to try out.
  • Meet CoffeeScript is a 75-minute long screencast by PeepCode. Highly memorable for its animations which demonstrate transforming CoffeeScript into the equivalent JS.
  • If you're looking for less of a time commitment, RailsCasts' CoffeeScript Basics should have you covered, hitting all of the important notes about CoffeeScript in 11 minutes.

Examples

The best list of open-source CoffeeScript examples can be found on GitHub. But just to throw out few more:

  • github's Hubot, a friendly IRC robot that can perform any number of useful and useless tasks.
  • sstephenson's Pow, a zero-configuration Rack server, with comprehensive annotated source.
  • technoweenie's Coffee-Resque, a port of Resque for Node.js.
  • assaf's Zombie.js, a headless, full-stack, faux-browser testing library for Node.js.
  • jashkenas' Underscore.coffee, a port of the Underscore.js library of helper functions.
  • stephank's Orona, a remake of the Bolo tank game for modern browsers.
  • github's Atom, a hackable text editor built on web technologies.

Resources

  • Source Code
    Use bin/coffee to test your changes,
    bin/cake test to run the test suite,
    bin/cake build to rebuild the CoffeeScript compiler, and
    bin/cake build:parser to regenerate the Jison parser if you're working on the grammar.

    git checkout lib && bin/cake build:full is a good command to run when you're working on the core language. It'll refresh the lib directory (in case you broke something), build your altered compiler, use that to rebuild itself (a good sanity test) and then run all of the tests. If they pass, there's a good chance you've made a successful change.
  • CoffeeScript Issues
    Bug reports, feature proposals, and ideas for changes to the language belong here.
  • CoffeeScript Google Group
    If you'd like to ask a question, the mailing list is a good place to get help.
  • The CoffeeScript Wiki
    If you've ever learned a neat CoffeeScript tip or trick, or ran into a gotcha — share it on the wiki. The wiki also serves as a directory of handy text editor extensions, web framework plugins, and general CoffeeScript build tools.
  • The FAQ
    Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
  • JS2Coffee
    Is a very well done reverse JavaScript-to-CoffeeScript compiler. It's not going to be perfect (infer what your JavaScript classes are, when you need bound functions, and so on...) — but it's a great starting point for converting simple scripts.
  • High-Rez Logo
    The CoffeeScript logo is available in Illustrator, EPS and PSD formats, for use in presentations.

Web Chat (IRC)

Quick help and advice can usually be found in the CoffeeScript IRC room. Join #coffeescript on irc.freenode.net, or click the button below to open a webchat session on this page.

Change Log

1.9.3
  • Bugfix for interpolation in the first key of an object literal in an implicit call.
  • Fixed broken error messages in the REPL, as well as a few minor bugs with the REPL.
  • Fixed source mappings for tokens at the beginning of lines when compiling with the --bare option. This has the nice side effect of generating smaller source maps.
  • Slight formatting improvement of compiled block comments.
  • Better error messages for on, off, yes and no.

1.9.2
  • Fixed a watch mode error introduced in 1.9.1 when compiling multiple files with the same filename.
  • Bugfix for yield around expressions containing this.
  • Added a Ruby-style -r option to the REPL, which allows requiring a module before execution with --eval or --interactive.
  • In <script type="text/coffeescript"> tags, to avoid possible duplicate browser requests for .coffee files, you can now use the data-src attribute instead of src.
  • Minor bug fixes for IE8, strict ES5 regular expressions and Browserify.

1.9.1
  • Interpolation now works in object literal keys (again). You can use this to dynamically name properties.
  • Internal compiler variable names no longer start with underscores. This makes the generated JavaScript a bit prettier, and also fixes an issue with the completely broken and ungodly way that AngularJS "parses" function arguments.
  • Fixed a few yield-related edge cases with yield return and yield throw.
  • Minor bug fixes and various improvements to compiler error messages.

1.9.0
  • CoffeeScript now supports ES6 generators. A generator is simply a function that yields.
  • More robust parsing and improved error messages for strings and regexes — especially with respect to interpolation.
  • Changed strategy for the generation of internal compiler variable names. Note that this means that @example function parameters are no longer available as naked example variables within the function body.
  • Fixed REPL compatibility with latest versions of Node and Io.js.
  • Various minor bug fixes.

1.8.0
  • The --join option of the CLI is now deprecated.
  • Source maps now use .js.map as file extension, instead of just .map.
  • The CLI now exits with the exit code 1 when it fails to write a file to disk.
  • The compiler no longer crashes on unterminated, single-quoted strings.
  • Fixed location data for string interpolations, which made source maps out of sync.
  • The error marker in error messages is now correctly positioned if the code is indented with tabs.
  • Fixed a slight formatting error in CoffeeScript’s source map-patched stack traces.
  • The %% operator now coerces its right operand only once.
  • It is now possible to require CoffeeScript files from Cakefiles without having to register the compiler first.
  • The CoffeeScript REPL is now exported and can be required using require 'coffee-script/repl'.
  • Fixes for the REPL in Node 0.11.

1.7.1
  • Fixed a typo that broke node module lookup when running a script directly with the coffee binary.

1.7.0
  • When requiring CoffeeScript files in Node you must now explicitly register the compiler. This can be done with require 'coffee-script/register' or CoffeeScript.register(). Also for configuration such as Mocha's, use coffee-script/register.
  • Improved error messages, source maps and stack traces. Source maps now use the updated //# syntax.
  • Leading . now closes all open calls, allowing for simpler chaining syntax.
$ 'body'
.click (e) ->
  $ '.box'
  .fadeIn 'fast'
  .addClass '.active'
.css 'background', 'white'


$('body').click(function(e) {
  return $('.box').fadeIn('fast').addClass('.active');
}).css('background', 'white');
load

  • Added **, // and %% operators and ... expansion in parameter lists and destructuring expressions.
  • Multiline strings are now joined by a single space and ignore all indentation. A backslash at the end of a line can denote the amount of whitespace between lines, in both strings and heredocs. Backslashes correctly escape whitespace in block regexes.
  • Closing brackets can now be indented and therefore no longer cause unexpected error.
  • Several breaking compilation fixes. Non-callable literals (strings, numbers etc.) don't compile in a call now and multiple postfix conditionals compile properly. Postfix conditionals and loops always bind object literals. Conditional assignment compiles properly in subexpressions. super is disallowed outside of methods and works correctly inside for loops.
  • Formatting of compiled block comments has been improved.
  • No more -p folders on Windows.
  • The options object passed to CoffeeScript is no longer mutated.

1.6.3
  • The CoffeeScript REPL now remembers your history between sessions. Just like a proper REPL should.
  • You can now use require in Node to load .coffee.md Literate CoffeeScript files. In the browser, text/literate-coffeescript script tags.
  • The old coffee --lint command has been removed. It was useful while originally working on the compiler, but has been surpassed by JSHint. You may now use -l to pass literate files in over stdio.
  • Bugfixes for Windows path separators, catch without naming the error, and executable-class-bodies-with- prototypal-property-attachment.

1.6.2
  • Source maps have been used to provide automatic line-mapping when running CoffeeScript directly via the coffee command, and for automatic line-mapping when running CoffeeScript directly in the browser. Also, to provide better error messages for semantic errors thrown by the compiler — with colors, even.
  • Improved support for mixed literate/vanilla-style CoffeeScript projects, and generating source maps for both at the same time.
  • Fixes for 1.6.x regressions with overriding inherited bound functions, and for Windows file path management.
  • The coffee command can now correctly fork() both .coffee and .js files. (Requires Node.js 0.9+)

1.6.1
  • First release of source maps. Pass the --map flag to the compiler, and off you go. Direct all your thanks over to Jason Walton.
  • Fixed a 1.5.0 regression with multiple implicit calls against an indented implicit object. Combinations of implicit function calls and implicit objects should generally be parsed better now — but it still isn't good style to nest them too heavily.
  • .coffee.md is now also supported as a Literate CoffeeScript file extension, for existing tooling. .litcoffee remains the canonical one.
  • Several minor fixes surrounding member properties, bound methods and super in class declarations.

1.5.0
  • First release of Literate CoffeeScript.
  • The CoffeeScript REPL is now based on the Node.js REPL, and should work better and more familiarly.
  • Returning explicit values from constructors is now forbidden. If you want to return an arbitrary value, use a function, not a constructor.
  • You can now loop over an array backwards, without having to manually deal with the indexes: for item in list by -1
  • Source locations are now preserved in the CoffeeScript AST, although source maps are not yet being emitted.

1.4.0
  • The CoffeeScript compiler now strips Microsoft's UTF-8 BOM if it exists, allowing you to compile BOM-borked source files.
  • Fix Node/compiler deprecation warnings by removing registerExtension, and moving from path.exists to fs.exists.
  • Small tweaks to splat compilation, backticks, slicing, and the error for duplicate keys in object literals.

1.3.3
  • Due to the new semantics of JavaScript's strict mode, CoffeeScript no longer guarantees that constructor functions have names in all runtimes. See #2052 for discussion.
  • Inside of a nested function inside of an instance method, it's now possible to call super more reliably (walks recursively up).
  • Named loop variables no longer have different scoping heuristics than other local variables. (Reverts #643)
  • Fix for splats nested within the LHS of destructuring assignment.
  • Corrections to our compile time strict mode forbidding of octal literals.

1.3.1
  • CoffeeScript now enforces all of JavaScript's Strict Mode early syntax errors at compile time. This includes old-style octal literals, duplicate property names in object literals, duplicate parameters in a function definition, deleting naked variables, setting the value of eval or arguments, and more. See a full discussion at #1547.
  • The REPL now has a handy new multi-line mode for entering large blocks of code. It's useful when copy-and-pasting examples into the REPL. Enter multi-line mode with Ctrl-V. You may also now pipe input directly into the REPL.
  • CoffeeScript now prints a Generated by CoffeeScript VERSION header at the top of each compiled file.
  • Conditional assignment of previously undefined variables a or= b is now considered a syntax error.
  • A tweak to the semantics of do, which can now be used to more easily simulate a namespace: do (x = 1, y = 2) -> ...
  • Loop indices are now mutable within a loop iteration, and immutable between them.
  • Both endpoints of a slice are now allowed to be omitted for consistency, effectively creating a shallow copy of the list.
  • Additional tweaks and improvements to coffee --watch under Node's "new" file watching API. Watch will now beep by default if you introduce a syntax error into a watched script. We also now ignore hidden directories by default when watching recursively.

1.2.0
  • Multiple improvements to coffee --watch and --join. You may now use both together, as well as add and remove files and directories within a --watch'd folder.
  • The throw statement can now be used as part of an expression.
  • Block comments at the top of the file will now appear outside of the safety closure wrapper.
  • Fixed a number of minor 1.1.3 regressions having to do with trailing operators and unfinished lines, and a more major 1.1.3 regression that caused bound functions within bound class functions to have the incorrect this.

1.1.3
  • Ahh, whitespace. CoffeeScript's compiled JS now tries to space things out and keep it readable, as you can see in the examples on this page.
  • You can now call super in class level methods in class bodies, and bound class methods now preserve their correct context.
  • JavaScript has always supported octal numbers 010 is 8, and hexadecimal numbers 0xf is 15, but CoffeeScript now also supports binary numbers: 0b10 is 2.
  • The CoffeeScript module has been nested under a subdirectory to make it easier to require individual components separately, without having to use npm. For example, after adding the CoffeeScript folder to your path: require('coffee-script/lexer')
  • There's a new "link" feature in Try CoffeeScript on this webpage. Use it to get a shareable permalink for your example script.
  • The coffee --watch feature now only works on Node.js 0.6.0 and higher, but now also works properly on Windows.
  • Lots of small bug fixes from @michaelficarra, @geraldalewis, @satyr, and @trevorburnham.

1.1.2 Fixes for block comment formatting, ?= compilation, implicit calls against control structures, implicit invocation of a try/catch block, variadic arguments leaking from local scope, line numbers in syntax errors following heregexes, property access on parenthesized number literals, bound class methods and super with reserved names, a REPL overhaul, consecutive compiled semicolons, block comments in implicitly called objects, and a Chrome bug.

1.1.1 Bugfix release for classes with external constructor functions, see issue #1182.

1.1.0 When running via the coffee executable, process.argv and friends now report coffee instead of node. Better compatibility with Node.js 0.4.x module lookup changes. The output in the REPL is now colorized, like Node's is. Giving your concatenated CoffeeScripts a name when using --join is now mandatory. Fix for lexing compound division /= as a regex accidentally. All text/coffeescript tags should now execute in the order they're included. Fixed an issue with extended subclasses using external constructor functions. Fixed an edge-case infinite loop in addImplicitParentheses. Fixed exponential slowdown with long chains of function calls. Globals no longer leak into the CoffeeScript REPL. Splatted parameters are declared local to the function.

1.0.1 Fixed a lexer bug with Unicode identifiers. Updated REPL for compatibility with Node.js 0.3.7. Fixed requiring relative paths in the REPL. Trailing return and return undefined are now optimized away. Stopped requiring the core Node.js "util" module for back-compatibility with Node.js 0.2.5. Fixed a case where a conditional return would cause fallthrough in a switch statement. Optimized empty objects in destructuring assignment.

1.0.0 CoffeeScript loops no longer try to preserve block scope when functions are being generated within the loop body. Instead, you can use the do keyword to create a convenient closure wrapper. Added a --nodejs flag for passing through options directly to the node executable. Better behavior around the use of pure statements within expressions. Fixed inclusive slicing through -1, for all browsers, and splicing with arbitrary expressions as endpoints.

0.9.6 The REPL now properly formats stacktraces, and stays alive through asynchronous exceptions. Using --watch now prints timestamps as files are compiled. Fixed some accidentally-leaking variables within plucked closure-loops. Constructors now maintain their declaration location within a class body. Dynamic object keys were removed. Nested classes are now supported. Fixes execution context for naked splatted functions. Bugfix for inversion of chained comparisons. Chained class instantiation now works properly with splats.

0.9.5 0.9.5 should be considered the first release candidate for CoffeeScript 1.0. There have been a large number of internal changes since the previous release, many contributed from satyr's Coco dialect of CoffeeScript. Heregexes (extended regexes) were added. Functions can now have default arguments. Class bodies are now executable code. Improved syntax errors for invalid CoffeeScript. undefined now works like null, and cannot be assigned a new value. There was a precedence change with respect to single-line comprehensions: result = i for i in list
used to parse as result = (i for i in list) by default ... it now parses as
(result = i) for i in list.

0.9.4 CoffeeScript now uses appropriately-named temporary variables, and recycles their references after use. Added require.extensions support for Node.js 0.3. Loading CoffeeScript in the browser now adds just a single CoffeeScript object to global scope. Fixes for implicit object and block comment edge cases.

0.9.3 CoffeeScript switch statements now compile into JS switch statements — they previously compiled into if/else chains for JavaScript 1.3 compatibility. Soaking a function invocation is now supported. Users of the RubyMine editor should now be able to use --watch mode.

0.9.2 Specifying the start and end of a range literal is now optional, eg. array[3..]. You can now say a not instanceof b. Fixed important bugs with nested significant and non-significant indentation (Issue #637). Added a --require flag that allows you to hook into the coffee command. Added a custom jsl.conf file for our preferred JavaScriptLint setup. Sped up Jison grammar compilation time by flattening rules for operations. Block comments can now be used with JavaScript-minifier-friendly syntax. Added JavaScript's compound assignment bitwise operators. Bugfixes to implicit object literals with leading number and string keys, as the subject of implicit calls, and as part of compound assignment.

0.9.1 Bugfix release for 0.9.1. Greatly improves the handling of mixed implicit objects, implicit function calls, and implicit indentation. String and regex interpolation is now strictly #{ ... } (Ruby style). The compiler now takes a --require flag, which specifies scripts to run before compilation.

0.9.0 The CoffeeScript 0.9 series is considered to be a release candidate for 1.0; let's give her a shakedown cruise. 0.9.0 introduces a massive backwards-incompatible change: Assignment now uses =, and object literals use :, as in JavaScript. This allows us to have implicit object literals, and YAML-style object definitions. Half assignments are removed, in favor of +=, or=, and friends. Interpolation now uses a hash mark # instead of the dollar sign $ — because dollar signs may be part of a valid JS identifier. Downwards range comprehensions are now safe again, and are optimized to straight for loops when created with integer endpoints. A fast, unguarded form of object comprehension was added: for all key, value of object. Mentioning the super keyword with no arguments now forwards all arguments passed to the function, as in Ruby. If you extend class B from parent class A, if A has an extended method defined, it will be called, passing in B — this enables static inheritance, among other things. Cleaner output for functions bound with the fat arrow. @variables can now be used in parameter lists, with the parameter being automatically set as a property on the object — useful in constructors and setter functions. Constructor functions can now take splats.

0.7.2 Quick bugfix (right after 0.7.1) for a problem that prevented coffee command-line options from being parsed in some circumstances.

0.7.1 Block-style comments are now passed through and printed as JavaScript block comments -- making them useful for licenses and copyright headers. Better support for running coffee scripts standalone via hashbangs. Improved syntax errors for tokens that are not in the grammar.

0.7.0 Official CoffeeScript variable style is now camelCase, as in JavaScript. Reserved words are now allowed as object keys, and will be quoted for you. Range comprehensions now generate cleaner code, but you have to specify by -1 if you'd like to iterate downward. Reporting of syntax errors is greatly improved from the previous release. Running coffee with no arguments now launches the REPL, with Readline support. The <- bind operator has been removed from CoffeeScript. The loop keyword was added, which is equivalent to a while true loop. Comprehensions that contain closures will now close over their variables, like the semantics of a forEach. You can now use bound function in class definitions (bound to the instance). For consistency, a in b is now an array presence check, and a of b is an object-key check. Comments are no longer passed through to the generated JavaScript.

0.6.2 The coffee command will now preserve directory structure when compiling a directory full of scripts. Fixed two omissions that were preventing the CoffeeScript compiler from running live within Internet Explorer. There's now a syntax for block comments, similar in spirit to CoffeeScript's heredocs. ECMA Harmony DRY-style pattern matching is now supported, where the name of the property is the same as the name of the value: {name, length}: func. Pattern matching is now allowed within comprehension variables. unless is now allowed in block form. until loops were added, as the inverse of while loops. switch statements are now allowed without switch object clauses. Compatible with Node.js v0.1.95.

0.6.1 Upgraded CoffeeScript for compatibility with the new Node.js v0.1.90 series.

0.6.0 Trailing commas are now allowed, a-la Python. Static properties may be assigned directly within class definitions, using @property notation.

0.5.6 Interpolation can now be used within regular expressions and heredocs, as well as strings. Added the <- bind operator. Allowing assignment to half-expressions instead of special ||=-style operators. The arguments object is no longer automatically converted into an array. After requiring coffee-script, Node.js can now directly load .coffee files, thanks to registerExtension. Multiple splats can now be used in function calls, arrays, and pattern matching.

0.5.5 String interpolation, contributed by Stan Angeloff. Since --run has been the default since 0.5.3, updating --stdio and --eval to run by default, pass --compile as well if you'd like to print the result.

0.5.4 Bugfix that corrects the Node.js global constants __filename and __dirname. Tweaks for more flexible parsing of nested function literals and improperly-indented comments. Updates for the latest Node.js API.

0.5.3 CoffeeScript now has a syntax for defining classes. Many of the core components (Nodes, Lexer, Rewriter, Scope, Optparse) are using them. Cakefiles can use optparse.coffee to define options for tasks. --run is now the default flag for the coffee command, use --compile to save JavaScripts. Bugfix for an ambiguity between RegExp literals and chained divisions.

0.5.2 Added a compressed version of the compiler for inclusion in web pages as
extras/coffee-script.js. It'll automatically run any script tags with type text/coffeescript for you. Added a --stdio option to the coffee command, for piped-in compiles.

0.5.1 Improvements to null soaking with the existential operator, including soaks on indexed properties. Added conditions to while loops, so you can use them as filters with when, in the same manner as comprehensions.

0.5.0 CoffeeScript 0.5.0 is a major release, While there are no language changes, the Ruby compiler has been removed in favor of a self-hosting compiler written in pure CoffeeScript.

0.3.2 @property is now a shorthand for this.property.
Switched the default JavaScript engine from Narwhal to Node.js. Pass the --narwhal flag if you'd like to continue using it.

0.3.0 CoffeeScript 0.3 includes major syntax changes:
The function symbol was changed to ->, and the bound function symbol is now =>.
Parameter lists in function definitions must now be wrapped in parentheses.
Added property soaking, with the ?. operator.
Made parentheses optional, when invoking functions with arguments.
Removed the obsolete block literal syntax.

0.2.6 Added Python-style chained comparisons, the conditional existence operator ?=, and some examples from Beautiful Code. Bugfixes relating to statement-to-expression conversion, arguments-to-array conversion, and the TextMate syntax highlighter.

0.2.5 The conditions in switch statements can now take multiple values at once — If any of them are true, the case will run. Added the long arrow ==>, which defines and immediately binds a function to this. While loops can now be used as expressions, in the same way that comprehensions can. Splats can be used within pattern matches to soak up the rest of an array.

0.2.4 Added ECMAScript Harmony style destructuring assignment, for dealing with extracting values from nested arrays and objects. Added indentation-sensitive heredocs for nicely formatted strings or chunks of code.

0.2.3 Axed the unsatisfactory ino keyword, replacing it with of for object comprehensions. They now look like: for prop, value of object.

0.2.2 When performing a comprehension over an object, use ino, instead of in, which helps us generate smaller, more efficient code at compile time.
Added :: as a shorthand for saying .prototype.
The "splat" symbol has been changed from a prefix asterisk *, to a postfix ellipsis ...
Added JavaScript's in operator, empty return statements, and empty while loops.
Constructor functions that start with capital letters now include a safety check to make sure that the new instance of the object is returned.
The extends keyword now functions identically to goog.inherits in Google's Closure Library.

0.2.1 Arguments objects are now converted into real arrays when referenced.

0.2.0 Major release. Significant whitespace. Better statement-to-expression conversion. Splats. Splice literals. Object comprehensions. Blocks. The existential operator. Many thanks to all the folks who posted issues, with special thanks to Liam O'Connor-Davis for whitespace and expression help.

0.1.6 Bugfix for running coffee --interactive and --run from outside of the CoffeeScript directory. Bugfix for nested function/if-statements.

0.1.5 Array slice literals and array comprehensions can now both take Ruby-style ranges to specify the start and end. JavaScript variable declaration is now pushed up to the top of the scope, making all assignment statements into expressions. You can use \ to escape newlines. The coffee-script command is now called coffee.

0.1.4 The official CoffeeScript extension is now .coffee instead of .cs, which properly belongs to C#. Due to popular demand, you can now also use = to assign. Unlike JavaScript, = can also be used within object literals, interchangeably with :. Made a grammatical fix for chained function calls like func(1)(2)(3)(4). Inheritance and super no longer use __proto__, so they should be IE-compatible now.

0.1.3 The coffee command now includes --interactive, which launches an interactive CoffeeScript session, and --run, which directly compiles and executes a script. Both options depend on a working installation of Narwhal. The aint keyword has been replaced by isnt, which goes together a little smoother with is. Quoted strings are now allowed as identifiers within object literals: eg. {"5+5": 10}. All assignment operators now use a colon: +:, -:, *:, etc.

0.1.2 Fixed a bug with calling super() through more than one level of inheritance, with the re-addition of the extends keyword. Added experimental Narwhal support (as a Tusk package), contributed by Tom Robinson, including bin/cs as a CoffeeScript REPL and interpreter. New --no-wrap option to suppress the safety function wrapper.

0.1.1 Added instanceof and typeof as operators.

0.1.0 Initial CoffeeScript release.

1.9.3~dfsg/Cakefile0000644000000000000000000002475312531364553012736 0ustar rootrootfs = require 'fs' path = require 'path' _ = require 'underscore' CoffeeScript = require './lib/coffee-script' {spawn, exec} = require 'child_process' helpers = require './lib/coffee-script/helpers' # ANSI Terminal Colors. bold = red = green = reset = '' unless process.env.NODE_DISABLE_COLORS bold = '\x1B[0;1m' red = '\x1B[0;31m' green = '\x1B[0;32m' reset = '\x1B[0m' # Built file header. header = """ /** * CoffeeScript Compiler v#{CoffeeScript.VERSION} * http://coffeescript.org * * Copyright 2011, Jeremy Ashkenas * Released under the MIT License */ """ # Build the CoffeeScript language from source. build = (cb) -> files = fs.readdirSync 'src' files = ('src/' + file for file in files when file.match(/\.(lit)?coffee$/)) run ['-c', '-o', 'lib/coffee-script'].concat(files), cb # Run a CoffeeScript through our node/coffee interpreter. run = (args, cb) -> proc = spawn 'node', ['bin/coffee'].concat(args) proc.stderr.on 'data', (buffer) -> console.log buffer.toString() proc.on 'exit', (status) -> process.exit(1) if status != 0 cb() if typeof cb is 'function' # Log a message with a color. log = (message, color, explanation) -> console.log color + message + reset + ' ' + (explanation or '') codeFor = -> counter = 0 hljs = require 'highlight.js' hljs.configure classPrefix: '' (file, executable = false, showLoad = true) -> counter++ return unless fs.existsSync "documentation/js/#{file}.js" cs = fs.readFileSync "documentation/coffee/#{file}.coffee", 'utf-8' js = fs.readFileSync "documentation/js/#{file}.js", 'utf-8' js = js.replace /^\/\/ generated.*?\n/i, '' cshtml = "
#{hljs.highlight('coffeescript', cs).value}
" jshtml = "
#{hljs.highlight('javascript', js).value}
" append = if executable is yes then '' else "alert(#{executable});" if executable and executable != yes cs.replace /(\S)\s*\Z/m, "$1\n\nalert #{executable}" run = if executable is true then 'run' else "run: #{executable}" name = "example#{counter}" script = "" load = if showLoad then "
load
" else '' button = if executable then "
#{run}
" else '' "
#{cshtml}#{jshtml}#{script}#{load}#{button}
" monthNames = [ 'January' 'February' 'March' 'April' 'May' 'June' 'July' 'August' 'September' 'October' 'November' 'December' ] formatDate = (date) -> date.replace /^(\d\d\d\d)-(\d\d)-(\d\d)$/, (match, $1, $2, $3) -> "#{monthNames[$2 - 1]} #{+$3}, #{$1}" releaseHeader = (date, version, prevVersion) -> """
#{prevVersion and "#{version}" or version} """ option '-p', '--prefix [DIR]', 'set the installation prefix for `cake install`' task 'install', 'install CoffeeScript into /usr/local (or --prefix)', (options) -> base = options.prefix or '/usr/local' lib = "#{base}/lib/coffee-script" bin = "#{base}/bin" node = "~/.node_libraries/coffee-script" console.log "Installing CoffeeScript to #{lib}" console.log "Linking to #{node}" console.log "Linking 'coffee' to #{bin}/coffee" exec([ "mkdir -p #{lib} #{bin}" "cp -rf bin lib LICENSE README.md package.json src #{lib}" "ln -sfn #{lib}/bin/coffee #{bin}/coffee" "ln -sfn #{lib}/bin/cake #{bin}/cake" "mkdir -p ~/.node_libraries" "ln -sfn #{lib}/lib/coffee-script #{node}" ].join(' && '), (err, stdout, stderr) -> if err then console.log stderr.trim() else log 'done', green ) task 'build', 'build the CoffeeScript language from source', build task 'build:full', 'rebuild the source twice, and run the tests', -> build -> build -> csPath = './lib/coffee-script' csDir = path.dirname require.resolve csPath for mod of require.cache when csDir is mod[0 ... csDir.length] delete require.cache[mod] unless runTests require csPath process.exit 1 task 'build:parser', 'rebuild the Jison parser (run build first)', -> helpers.extend global, require('util') require 'jison' parser = require('./lib/coffee-script/grammar').parser fs.writeFile 'lib/coffee-script/parser.js', parser.generate() task 'build:browser', 'rebuild the merged script for inclusion in the browser', -> code = '' for name in ['helpers', 'rewriter', 'lexer', 'parser', 'scope', 'nodes', 'sourcemap', 'coffee-script', 'browser'] code += """ require['./#{name}'] = (function() { var exports = {}, module = {exports: exports}; #{fs.readFileSync "lib/coffee-script/#{name}.js"} return module.exports; })(); """ code = """ (function(root) { var CoffeeScript = function() { function require(path){ return require[path]; } #{code} return require['./coffee-script']; }(); if (typeof define === 'function' && define.amd) { define(function() { return CoffeeScript; }); } else { root.CoffeeScript = CoffeeScript; } }(this)); """ unless process.env.MINIFY is 'false' {code} = require('uglify-js').minify code, fromString: true fs.writeFileSync 'extras/coffee-script.js', header + '\n' + code console.log "built ... running browser tests:" invoke 'test:browser' task 'doc:site', 'watch and continually rebuild the documentation for the website', -> source = 'documentation/index.html.js' exec 'bin/coffee -bc -o documentation/js documentation/coffee/*.coffee' do renderIndex = -> codeSnippetCounter = 0 rendered = _.template fs.readFileSync(source, 'utf-8'), codeFor: codeFor() releaseHeader: releaseHeader fs.writeFileSync 'index.html', rendered log "compiled", green, "#{source}" fs.watchFile source, interval: 200, renderIndex log "watching..." , green task 'doc:source', 'rebuild the internal documentation', -> exec 'node_modules/.bin/docco src/*.*coffee && cp -rf docs documentation && rm -r docs', (err) -> throw err if err task 'doc:underscore', 'rebuild the Underscore.coffee documentation page', -> exec 'node_modules/.bin/docco examples/underscore.coffee && cp -rf docs documentation && rm -r docs', (err) -> throw err if err task 'bench', 'quick benchmark of compilation time', -> {Rewriter} = require './lib/coffee-script/rewriter' sources = ['coffee-script', 'grammar', 'helpers', 'lexer', 'nodes', 'rewriter'] coffee = sources.map((name) -> fs.readFileSync "src/#{name}.coffee").join '\n' litcoffee = fs.readFileSync("src/scope.litcoffee").toString() fmt = (ms) -> " #{bold}#{ " #{ms}".slice -4 }#{reset} ms" total = 0 now = Date.now() time = -> total += ms = -(now - now = Date.now()); fmt ms tokens = CoffeeScript.tokens coffee, rewrite: no littokens = CoffeeScript.tokens litcoffee, rewrite: no, literate: yes tokens = tokens.concat(littokens) console.log "Lex #{time()} (#{tokens.length} tokens)" tokens = new Rewriter().rewrite tokens console.log "Rewrite#{time()} (#{tokens.length} tokens)" nodes = CoffeeScript.nodes tokens console.log "Parse #{time()}" js = nodes.compile bare: yes console.log "Compile#{time()} (#{js.length} chars)" console.log "total #{ fmt total }" # Run the CoffeeScript test suite. runTests = (CoffeeScript) -> CoffeeScript.register() startTime = Date.now() currentFile = null passedTests = 0 failures = [] global[name] = func for name, func of require 'assert' # Convenience aliases. global.CoffeeScript = CoffeeScript global.Repl = require './lib/coffee-script/repl' # Our test helper function for delimiting different test cases. global.test = (description, fn) -> try fn.test = {description, currentFile} fn.call(fn) ++passedTests catch e failures.push filename: currentFile error: e description: description if description? source: fn.toString() if fn.toString? # See http://wiki.ecmascript.org/doku.php?id=harmony:egal egal = (a, b) -> if a is b a isnt 0 or 1/a is 1/b else a isnt a and b isnt b # A recursive functional equivalence helper; uses egal for testing equivalence. arrayEgal = (a, b) -> if egal a, b then yes else if a instanceof Array and b instanceof Array return no unless a.length is b.length return no for el, idx in a when not arrayEgal el, b[idx] yes global.eq = (a, b, msg) -> ok egal(a, b), msg ? "Expected #{a} to equal #{b}" global.arrayEq = (a, b, msg) -> ok arrayEgal(a,b), msg ? "Expected #{a} to deep equal #{b}" # When all the tests have run, collect and print errors. # If a stacktrace is available, output the compiled function source. process.on 'exit', -> time = ((Date.now() - startTime) / 1000).toFixed(2) message = "passed #{passedTests} tests in #{time} seconds#{reset}" return log(message, green) unless failures.length log "failed #{failures.length} and #{message}", red for fail in failures {error, filename, description, source} = fail console.log '' log " #{description}", red if description log " #{error.stack}", red console.log " #{source}" if source return # Run every test in the `test` folder, recording failures. files = fs.readdirSync 'test' # Ignore generators test file if generators are not available generatorsAreAvailable = '--harmony' in process.execArgv or '--harmony-generators' in process.execArgv files.splice files.indexOf('generators.coffee'), 1 if not generatorsAreAvailable for file in files when helpers.isCoffee file literate = helpers.isLiterate file currentFile = filename = path.join 'test', file code = fs.readFileSync filename try CoffeeScript.run code.toString(), {filename, literate} catch error failures.push {filename, error} return !failures.length task 'test', 'run the CoffeeScript language test suite', -> runTests CoffeeScript task 'test:browser', 'run the test suite against the merged browser script', -> source = fs.readFileSync 'extras/coffee-script.js', 'utf-8' result = {} global.testingBrowser = yes (-> eval source).call result runTests result.CoffeeScript 1.9.3~dfsg/LICENSE0000644000000000000000000000205012531364553012277 0ustar rootrootCopyright (c) 2009-2015 Jeremy Ashkenas Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 1.9.3~dfsg/bower.json0000644000000000000000000000073312531364553013311 0ustar rootroot{ "name": "coffee-script", "version": "1.9.3", "main": [ "lib/coffee-script/coffee-script.js" ], "description": "Unfancy JavaScript", "keywords": [ "javascript", "language", "coffeescript", "compiler" ], "devDependencies": { "uglify-js": "~2.2", "jison": ">=0.2.0", "highlight.js": "~8.0.0", "underscore": "~1.5.2", "docco": "~0.6.2" }, "author": { "name": "Jeremy Ashkenas" }, "ignore": [ "test" ] } 1.9.3~dfsg/extras/0000755000000000000000000000000012531652342012577 5ustar rootroot1.9.3~dfsg/.npmignore0000644000000000000000000000015212531364553013272 0ustar rootroot*.coffee *.html .DS_Store .git* Cakefile documentation/ examples/ extras/coffee-script.js raw/ src/ test/ 1.9.3~dfsg/README.md0000644000000000000000000000367312531364553012565 0ustar rootroot { } } { { { } } } }{ { { }{ } } _____ __ __ { }{ }{ { } / ____| / _|/ _| .- { { } { }} -. | | ___ | |_| |_ ___ ___ ( { } { } { } } ) | | / _ \| _| _/ _ \/ _ \ |`-..________ ..-'| | |___| (_) | | | || __/ __/ | | \_____\___/|_| |_| \___|\___| | ;--. | (__ \ _____ _ _ | | ) ) / ____| (_) | | | |/ / | (___ ___ _ __ _ _ __ | |_ | ( / \___ \ / __| '__| | '_ \| __| | |/ ____) | (__| | | | |_) | |_ | | |_____/ \___|_| |_| .__/ \__| `-.._________..-' | | |_| CoffeeScript is a little language that compiles into JavaScript. ## Installation If you have the node package manager, npm, installed: ```shell npm install -g coffee-script ``` Leave off the `-g` if you don't wish to install globally. If you don't wish to use npm: ```shell git clone https://github.com/jashkenas/coffeescript.git sudo coffeescript/bin/cake install ``` ## Getting Started Execute a script: ```shell coffee /path/to/script.coffee ``` Compile a script: ```shell coffee -c /path/to/script.coffee ``` For documentation, usage, and examples, see: http://coffeescript.org/ To suggest a feature or report a bug: http://github.com/jashkenas/coffeescript/issues If you'd like to chat, drop by #coffeescript on Freenode IRC. The source repository: https://github.com/jashkenas/coffeescript.git Changelog: http://coffeescript.org/#changelog Our lovely and talented contributors are listed here: http://github.com/jashkenas/coffeescript/contributors 1.9.3~dfsg/documentation/0000755000000000000000000000000012531364553014146 5ustar rootroot1.9.3~dfsg/documentation/images/0000755000000000000000000000000012531364553015413 5ustar rootroot1.9.3~dfsg/documentation/images/button_bg_green.gif0000644000000000000000000000013712531364553021246 0ustar rootrootGIF89a3n={*\:u0g-c2k;x9s,`6r>|!, pIg8)`HIB;1.9.3~dfsg/documentation/images/button_bg.png0000644000000000000000000000021212531364553020077 0ustar rootrootPNG  IHDRatEXtSoftwareAdobe ImageReadyqe<,IDATxb~)P{;w{FIENDB`1.9.3~dfsg/documentation/images/logo.png0000644000000000000000000003045712531364553017072 0ustar rootrootPNG  IHDRM5dtEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp -IDATx}KQV ( bMbѨ11&VK,1Ŗhbg4b5 ( A|;;޸2C 24aTX#3q`pCOy㿽1={To\F 0m,ƯL#̐!CL#LCg0S~M淑7ZS77E6޸x8ct 7Ʈ3;oL$'6iړcolUh卥xox3f؝Y9ļCR$u7vƖ!}I\xl2!ܔbc "L vojO >$-VH̞x;@^Zفqc?By }h8Qp0%ޘ8o걞?Gl@=iΜl*3ahv!2-~Gj? b>[SRAxW)~g7>oa&wJ%enzGP MJ| `I2V\37~ ~P.x'WxlZԧ<,4†r8%} Zq1{0?IɊoq pR55ݷh)gLs)yü={qƙ.a>7&`%g"8O\tssDcKP}5Cܑup*V'u7J#ԞAi247 !-aJ`$5^8JՔ;+E|%_dwz\$'Ѵ |"+q_.)zj] R;L|Ip4Nnߏ8 HoAB(8y`Zp2&p}mw=7B?ڊq̻_9-"Ls.LïpP5ˀh9kO1{4L$sC;5Uu & BJUm 5Q0BJ̟%9~h& M ˣJ&?-jzo8p(,W"`Kv)6Q`ĝp ە_f>0L+H\0&o2 HtUdWK:]q !s*屫%ܟ h!1^c]}4>Hv̈́0T1 8Y;|׮3^cD 7Q5y@X`g ~q ?sB'*Wb×25^@B4$>6\S dz"FAMMo%*ǂ9pKG R`JS ^`~k23LЯ1e$Lq\ukN7,t\76 k3Fo qqE$\D%|N_lj_(`KxV0 4qK39[C*'" - `vwۋ>'{q3 ʝoG5", ~)S:/-Q8NJ꫍NFJy=,˄-z cQ\D'Hh~ HOt|޲$Lk`\y#"$F7M3i-6&BbH9_܋#r([EdR`NDI'ǥ4[^WMt!v ۑ5(t؋ jЂ?%nP[!mh8vL>"*ǁhw} Kjs,&=}׊$صL+CImbNޅ4=LS9>B  f@"1Ao32^Im)/ jk.hI\ KJxLqo9%yASTr\ e ZGN_ƔF D=ۉ#:$SD&s +R A 0nB7vdt[KOeXN]<}6|"6mNÚSyw2J K6,Ea;j0ߏ!?|=/أT!h)]'y;BA~1@rNI`ZFVF7#ߡ.( ZK NؖL+0mfa$g#(b4i i-Ŗgd,QLk28 Zܪmp=Ȱ.,I[]aqi(LlW%y4hz/PBKyE|= ~qvq# Io,M Ք*%i'0"huj霫i%#bs@5D#%f -wj)w̙3֊UICGv i[RB6թGQMR\6jLh":.H%'vډD%6McgIW4s35ҰO1aPk؂V!BH R sTUȞ,fv0N bd7G]9jiX$c4- 0Wyqp9IyƘGN"`S# mKIP_19R2%0K`55;x),Ph)H \`Efk#H}Tpc̿ᳬpT췸(y/w b*B#t7AQKa8I:>##9(hin #%ׅJfAs"C;Ιs ^ȺڍJSJҝQKo.lAkAk-vu@y~HOdY6^=dg鳚v6mAw… K2b Al!>vls/w -rO]H ;Phj}Ri/킒؜{@H`FL܍yw_K.Ҋt3Q'Hik\3#f5q T(4pɾ .NH Zm (Ǹ.W;ޑ"ѿxX(ta"_RK ^Em=6%o?B‹i:O+>U;=13,m HؓJT% 2mw4eDIo0I<|P/( $* 1FҺ^Ȇ~Bۓ8r԰gDi _ixI$?b5S^{RY/rҦQYS팀] QH@O $A3hB"y%$*~L # 'l~7=N|CRmw`W2^Y&QX8x%c@ 0_xeo/U0B&^(`)slqQϿٜ;ǵbZk6. A V_BFuAk /p]ꊦsD󭽃Bd`U+DaG؉Z~2V Gpm'ҋ0LwmeoQ G/h57Zn=yp- ބ ii<[+p DS7L ax$gZ î%X鵅%-5Tp@š2 Kh@s[5D "KsR2'5x^uw]m~W[\iWKgR? j1%hٸ}rS{%~'PiFcӇ]2YB$)'.|%0"ÈkJ :5/ "G liY7릁`#fC_zK6&8_3q7Vd(^4_XJOۦE4iKy|B j; hBT]@>$\Ni$m55l0`R0݆;C7ϴMda;ވMEv[zMǂ{$l{04'/> /R3@2am+z+#Ocg\gGNj>ls,-_>BVj"F|_F-M_"w%Y1ol~>w򜏇hwyZiD(%^:"'JOfLm`1ige Mh LLGIq7Y`*t[d뚈 5hd7tZo;AA[nGGћ̢ے1i-ؕ{cnP(@P.U^4->8wEW |h?U;֘=w.XljX.2se6maB+H{j7l-a'\N!_i|S()|5sE_S6 Қ@@XqK"O,~Ƹl̉&aQ<\%Zw㾇QBbiRp -׍j]`듸C~}фi aIhAJ*Df0醕+Njq б8 DhiC3K#Uu9.} G3PSHE뗛#jJZA0]2ޓ1`hg-`=ra3BۋKȆ{wKy i#6!=qc!h[L)t>>J@ӖT6!c=1xEhe9@b "7R  )fF= 8Cҿw6}~9 P͟)5bv>p6&B Y} e^o`/,9pssՁ^DKĂQмߒrXSUwc%a$| M,"; ̤Pho۠itj]KyyEs!'a5+ɐwKi;:H(}} WC 3"fie0Q5Tj(&SAAL4pS)9lŻ+9!E BԾH ZhhuRxyK`YO4|hVvZ2`!>IbX#\ZHMa~<%.p-36Z*vLM(T?dg V1\ [FXhbvM iMujz85RP#1CMYF*+15 ']J q#`%lTHb8v~&,m 'vok`"(m D6%Fhy&p碏TLSSѩh8}Q]EgV˴#3Ahv޴{3%.N%˽Zj铬u p/x0Y!}kiM4B3kZJ1MtV ]' rζ}0G`qDŢZ7gD>-vhS؎}HiAq!Bgy({Sч6w  b-P;W#[Xc>8J,QZDg62Lu5fHk-NA`>Ͽ1uIcyЎ[1:^VFֽ k,.agW@y6ʀFW{#):ǩV82y[4ҕefKM#7UAA޽ƧbB&(?'o[Zk*j5Bhc X)1h~wsDEt- 6i9C8nR`^7mSgS߽" tJ3b sF67-wRH~5 lW;Ky,|lc}M@幾]5(?˾[Zie%X'07~cgñyWc!$2b QP76ITҀB>oj8~_RwyzEamn/L ކtHםhQFAK8upY(hi`ԔB`mB5@p)J` )k[&E3hrqsqߝS|d!b_{ܜ_N/֔/qLZZv&+kA T\W$)]-J@4pyS£={q,mi"퉚Vbg>3= ?ᷭ#L0M-# eF C=pݸ"G*g ϥrUG,qEa:=M2O9U E6&Y;ǜ2wH$Z#n_4ܢatM0-)I.o>1$`uvRZS>;{M?G`L 2v"#ךXlm!­6J7N֬S]9r3c&4+(}ൄphĚ&kֳm,QDX4ƒE R`E_"s|s1(V{<8Nvp}p]{ n9 BRoݭ6v=->9ߊXWi8͔pVNkM[|)/x^J|sj ~I%PN/?UE->c\ &-h6 mbX,Nyj"1W?>X5,I #6PFC苜oNiAs7qY5#d {koFXH➳w"#DBKCoAh96 9OAd^Zgcȃ[pu ~먻Kx>XD:, 듑!%ǝɎ<8/h諪75<!7&PwbBy=䋢-Q!B` Lb@DMeq37T^+J5Z}PdZ->&GZ&:⹂{VL[ L_q]9 ;Ο!b3U׈> OPYٞtX$2 Ki[7'NC }sƷ!_`Z}5ej#Lܥh$1nkLg֎7Mx-̬tv;OuD7;tӎ2#3G[^/ap|E0#( oE dNƩ{G@ ;C D>EYU Ђ|s8] /LJ̅'ZLQf C#!#Zs*3po(brK٣poT mL?~+3$x L0i= [ 0B }"4ڞ)9" ?:݋n^t%{E' $ cZiТ~IZg 7ICDv%ǃ75[|D+G K|_+bĘ:t7C@B<;]iT'=U򛯩 Lh14cQH{Ce]fP@EXdnW D#<V{u1q>v* N{@ H!0sz|׃I+^k<SZp!#ipm I7p!<5\ ^kuc&yFV_Vrz`l:Yc0BCܚ !X#PӀV6ҊZn:Ƹ7!O$Zvp(4PqJsyٹX60%o^ 2bvP֝Z\u=}M&Jq0% ,G֗ԑq`S#XXgڌ4Oya0 Q\4QMi ɔ #&%0(f7t0b;J(EP(`E87R&> l h"01\-77vL0Cb!7ߤvW۬^K*CMo& 6,zָJ~аH(e9acF*WQWkxMҫPFHY6oQ0̌4#Zڎ4{2d(vҴa0b1"p6GRa$Ӹ86^x򜯈;(ѧb^O&d]V>.^+CkZ#p9L ~*⻳ B24!}1#:OP hP汇CV@XRyR0*{Ez(C% ?Zasgyj*E]иV?i! ȿmHz241< -'Q3<N/K%W)TD<s ,*LƏ$⁆s dhB@Y?m Ԡ]^ܲ{L ڂ䪡پ( >}f]%yqxw6{=fţ}?i-9A#%W1>c兴|3S:Z= M = 6 kYu#_Lģ*o@PE m}E-Zd԰&;ѲLrlEfv:t\ې4BߪU51(o\4(J塩i.^E&`3M"eDwETQ Dgk(^_\a|B$M5dh@؞Jֲ16@U]]]~Y(ѢXԳ$Wc@d0̥(˶; D M2BҦj_*֊gIENDB`1.9.3~dfsg/documentation/images/screenshadow.png0000644000000000000000000001054412531364553020612 0ustar rootrootPNG  IHDR,tEXtSoftwareAdobe ImageReadyqe<IDATx r۸Q5tŚTܷv,k$?w?]?~_|^^kwxЍ{_oCtP&]w`m˃N!& F~qc҄!sA:'A4xNқHZsKaуpKO)r;$د<' b^HvUHr)z0xp{Rm: !M$Yaʠ7@NzgmBH in&JatRtBTh"GW@PNI8 ,?soO$AdRH[㯂?J4`XLII!鎏Gku7r ~7%0nLj@_Kҝ]Uq Y<q6Wt1:[K@zSGԧ+0oLꪠ-0ç&q=4uآ&*h+:~Jai~p0mdi/vR~AcT屒):^|@\ߩfLPTV2֜9E g ʜJjߐ}gҚ+ i6TKD/ݖV{giW kqH5<S+ٓG8lC]F#x $G|Y7S)!`U>.@!鎋Q|p}#xd8'Q<C$6z,z VuH]epAemGG9Ck^[gZٮIwabZZcDdbUoN ghFz7 >ǖ0nIj9c܌[և$ms%5$ O4$j@NkRFR!D/l2F{Wn+ׁzywڜ%"5#n[Ʒױ|9|&ũu@nFFZzL@ ~@)HRkYև<<\( ~Gxc]Kj7%|3  @i(pz^Do'}Bw@f\{h̓&C(`u/Ђó9%rT [[!gq~YtMM? H [WwDw\ʊ֕E\ʊչei7. K}HxdЊcv8-xG@kghž a 544Є+9(,"zo~AxC*Dd΀`lŸU*N# P`Dx,"Fdʀ˚t* ζHgd=" >`ySqѷx$"7N<ҎhXq }c)Ƹ ~7 g@[[Y7@@ [w7 ߈ Z>4 O!C9@yyy ~]"~sq܈$ L:j@(?"` L!/` L!/i@@Ѐ+u UXr: "/ĩAm`R?>1p 6ԦL!(}-GܚBG( kB+ Y@% lD`89@4lg`        @@@@@@@@ ͏?6gwϟ_/wmN C/30xy""<*:. J@ L<R OF xZ@L!<5}\ O^0c# [u)]Sq+ HeQ;1p( >@DDL Yڊ@qؾc!TDxCá!y{k-g0tx7 "x ݿ`Xdc;?`+ ɣ/7Z=` X1v@ZJDRvpl"Px< !lMjRp< 飞/ʶr}&]nI`c;7"PP< FDffo4((s[gY<c7fixvyw~`%7m.Ьf47nz;Y*ۅ#"/c VEB*H<KY>8GYHT&Y0wwT7a/ M[r++--`*_ߺwkǢk൭{iՍnkصGiS.;Ԗ#qoǜlݱzܮa $G;ֵGiBDRʖֲvhj~%W> ϗ?nX%U@SGo|w +iĖz<<Wn۫ nwaTMrl[ VwfV:X3 Hτ#1֡Y ">FkGv߬1wTX9y1ēgHv`[ j7V<."Xԑśp(hܬ}xǶ:śuÇ#[4F+>'&i#rQ8r ct|]ntOmo" pD1mn&?ZmDΙ<9(a?}w)u1'Y#cGM"̞-8$-[8닊Ön|+ !u|v,ݜ[V{ -}Fgiz72@zFTxlC8vKގ>j}I)OTS 6GMm*~Ad;e[4ҟJʱXM\Qԑb@!c# Q@F[Tpt:ҟF F=!xTՍc+K 9dx3/݄hhh<*Tgj5Vrv6==u%dV5L#`Xɯk.dvwS~O+z!U\BI}?UԑU,LlQH+I'~aN0esx1 !)_ rÑik H;7Hָx^NT)J8\% D֐TW^`,5&!.*oYy] x&C8~HQH,FekJt1z8(ےfg|DH^RDE,B8V~HvQH7ñ±˚>{qQR KXknlVtdPmS cֱ IT2yX*q%PL>mtTjA }߿TXXťZA`6WiC@2J>z1y CoffeeScript Logo 1.9.3~dfsg/documentation/images/favicon.ico0000644000000000000000000001456612531364553017550 0ustar rootroot (&  (N(  3ooooqqy(eRR52226p__ $oo2222222||fSS=%%2;##2222222H22aMMʿMgTT222222222}mm2+q22222222222^y2222222222222K55 udd2222222222222ĽHcPP28 R==kYYoo||}}||}mmhVVN9962udd:>VpppiWWiVVkYYɉzzkR:<n^KKn\\B8(05VZzzuddhVVV*VBB$o^^_LL՛~$tdd&o]] q``b&raap__0^VAA|| ygUUgUU"( @ 222222222222242z2222222=22222222222222222222222^2222222222j22222222222222222222722222222222222Q22222222222222222222222222222222242222222222$222222S2222222222222222222222222C22222:222222222222222222222222222222222O222222222222222222t2222222222022222222222222222222222)2222222222222222222222222222222222222222222s22222222222222222222222222222~22"22222222222222222222222292222!2222222222222222222222222222222222222222222222222222222222222;222222222222222222222222222222222222222222222222222222222222222222222@2222222222222222222222222222[222222222222`2@2)22222222&2=2[222222222222222G2222222224252324252"22222222;2222F222222222f222222222222222222m2#22222m2222"222222222s2`2S2Q2R2Q2G2D2V2v22222222-222222222e2&222222222222 2222222Q22222 22H222/22222T222228222H222222[22222 22222222222222z2v2222242<22 22222B22222B22(2222%2222222&28262122222a29242T222(22222 222222222222z222V222U22222222&222222222222222222 2W2S22222<2z22222?2222222221.9.3~dfsg/documentation/images/just_logo.svg0000644000000000000000000000407612531364553020150 0ustar rootroot CoffeeScript Logo 1.9.3~dfsg/documentation/images/background.png0000644000000000000000000000017312531364553020241 0ustar rootrootPNG  IHDR2^{tEXtSoftwareAdobe ImageReadyqe<IDATxb;,̃YL -Tjh[IENDB`1.9.3~dfsg/documentation/css/0000755000000000000000000000000012531364553014736 5ustar rootroot1.9.3~dfsg/documentation/css/docs.css0000644000000000000000000002267512531364553016414 0ustar rootrootbody { font-size: 14px; line-height: 21px; color: #333; background: #f6f6f6 url(../images/background.png); font-family: "Helvetica Neue", "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important; } .container { width: 950px; margin: 0; padding: 80px 0px 50px 50px; } p, li { width: 625px; } a { color: #191933; } h1, h2, h3, h4, h5, h6, b.header { font-size: 18px; color: #000; margin-top: 40px; margin-bottom: 15px; text-shadow: #fff 0 1px 1px; } br.clear { height: 0; clear: both; } ul { padding-left: 20px; } b.header { display: block; } li { margin-bottom: 10px; } table { margin: 16px 0 0 13px; padding: 0; width: 625px; } tr, td { margin: 0; padding: 0; } td { padding: 9px 15px 9px 0; vertical-align: top; } table.definitions { width: auto; margin: 30px 0; border-left: 5px solid rgba(0,0,0,0.2);; } table.definitions td { text-align: center; padding: 5px 20px; } code, pre, tt, textarea { font-family: Monaco, Consolas, "Lucida Console", monospace; font-size: 12px; line-height: 18px; color: #155; white-space: pre-wrap; word-wrap: break-word; } tt { display: inline-block; background: #fff; border: 1px solid #dedede; padding: 0px 0.2em; } pre { border-left: 5px solid rgba(0,0,0,0.2); padding: 3px 0 3px 12px; font-size: 12px; } pre.no_bar { border-left: 0; margin-left: 0; padding-left: 0; } .timestamp { font-size: 11px; font-weight: normal; text-transform: uppercase; } div.anchor { position: relative; top: -90px; margin: 0 0 -20px; } div.code { position: relative; background: #fff; border: 1px solid #d8d8d8; -webkit-box-shadow: 0px 0px 4px rgba(0,0,0,0.23); -moz-box-shadow: 0px 0px 4px rgba(0,0,0,0.23); box-shadow: 0px 0px 4px rgba(0,0,0,0.23); zoom: 1; } div.code .minibutton { text-transform: none; position: absolute; right: 8px; bottom: 8px; } div.code .load { left: 8px; right: auto; } div.code pre, div.code textarea { float: left; width: 450px; background: #fff; border-left: 1px dotted #d0d0d0; margin: 10px 0 15px 3px; padding: 0 0 0 12px; } div.code pre:first-child { border-left: 0; } #fadeout { z-index: 50; position: fixed; left: 0; top: 0; right: 0; height: 100px; background: -webkit-gradient(linear, left top, left bottom, from(rgba(255, 255, 255, 255)), to(rgba(255, 255, 255, 0))); background: -moz-linear-gradient(top, rgba(255, 255, 255, 255), rgba(255, 255, 255, 0)); } #flybar { position: fixed; z-index: 100; height: 50px; min-width: 490px; left: 40px; right: 40px; top: 25px; padding-left: 252px; background: #eee; background: -webkit-gradient(linear, left top, left bottom, from(#f8f8f8), to(#dadada)); background: -moz-linear-gradient(top, #f8f8f8, #dadada); border: 1px solid #aaa; border-top: 1px solid #bbb; border-bottom: 1px solid #888; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 3px 5px rgba(0,0,0,0.1); -moz-box-shadow: 0 3px 5px rgba(0,0,0,0.1); box-shadow: 0 3px 5px rgba(0,0,0,0.1); } #logo { display: block; outline: none; position: absolute; top: 0px; left: 10px; } #logo img { margin: 5px 0 0 3px; } .navigation { height: 50px; font-size: 11px; line-height: 50px; text-transform: uppercase; position: relative; float: left; padding: 0 20px; border: 1px solid #aaa; border-top: 0; border-bottom: 0; border-left-width: 0; cursor: pointer; } .navigation.toc { border-left-width: 1px; } .navigation:hover, .navigation.active { background: #eee; background: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#f8f8f8)); background: -moz-linear-gradient(top, #eee, #f8f8f8); } .navigation.active { height: 51px; color: #000; background: -webkit-gradient(linear, left top, left bottom, from(#e5e5e5), to(#fff)); background: -moz-linear-gradient(top, #e5e5e5, #fff); } .navigation .button { font-weight: bold; } .navigation .button::selection { background: transparent; } .navigation .contents { display: none; position: absolute; background: #fff; opacity: 0.97; top: 51px; left: 0; padding: 5px 0; margin-left: -1px; border: 1px solid #aaa; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 3px 5px rgba(0,0,0,0.2); -moz-box-shadow: 0 3px 5px rgba(0,0,0,0.2); box-shadow: 0 3px 5px rgba(0,0,0,0.2); } .navigation .contents a { display: block; width: 290px; text-transform: none; text-decoration: none; height: 12px; line-height: 12px; padding: 4px 10px; border: 1px solid transparent; border-left: 0; border-right: 0; } .navigation .contents a:hover { border-color: #ddd; background: #eee; } .navigation.active .contents { display: block; } .navigation .contents.menu { border-top: 0; -webkit-border-top-left-radius: 0; -moz-border-radius-topleft: 0; border-top-left-radius: 0; -webkit-border-top-right-radius: 0; -moz-border-radius-topright: 0; border-top-right-radius: 0; } .navigation .contents.repl_wrapper { padding: 0; position: fixed; width: auto; height: auto; left: 40px; top: 90px; right: 40px; bottom: 30px; background: -webkit-gradient(linear, left top, left bottom, from(#fafafa), to(#eaeaea)); } .navigation .repl_bridge { position: absolute; height: 12px; left: -1px; right: -1px; bottom: -14px; border: 1px solid #aaa; z-index: 5; background: #fff; display: none; border-top-color: #fff; border-bottom-color: #fff; } .navigation.active .repl_bridge { display: block; } .navigation .code .minibutton { top: 10px; right: 10px; width: 40px; text-transform: none; } .navigation .code a.minibutton.permalink { top: 38px; display: block; } .bookmark { display: block; width: 0; height: 0; position: relative; top: -90px; } .navigation .contents.repl_wrapper .code { cursor: text; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; background: #181a3a url(../images/banding.png); border: 2px solid #555; padding: 0; position: absolute; top: 15px; left: 15px; right: 15px; bottom: 15px; } .repl_wrapper .screenshadow { position: absolute; width: 200px; height: 150px; background: url(../images/screenshadow.png?2); } .repl_wrapper .screenshadow.tl { top: 0; left: 0; background-position: 0 0; } .repl_wrapper .screenshadow.tr { top: 0; right: 0; background-position: -200px 0; } .repl_wrapper .screenshadow.bl { bottom: 0; left: 0; background-position: 0 -150px; } .repl_wrapper .screenshadow.br { bottom: 0; right: 0; background-position: -200px -150px; } #repl_source, #repl_results { background: transparent; outline: none; margin: 5px 0 20px; color: #def; } #repl_results, #repl_source_wrap { width: auto; height: auto; position: absolute; margin-bottom: 0; top: 10px; left: 10px; right: 10px; bottom: 15px; } #repl_results.error { color: red } #repl_source_wrap { margin-left: 5px; width: 47%; right: 50%; float: left; } #repl_source { padding-left: 5px; width: 100%; height: 100%; border: 0; overflow-y: auto; resize: none; } #repl_results_wrap { white-space: pre; } #repl_results { text-transform: none; overflow-y: auto; left: 50%; border-left-color: #555; } /*----------------------------- Mini Buttons ---------------------------------*/ .minibutton { cursor: pointer; color: #333; text-shadow: #eee 0 1px 1px; font-weight: bold; font-size: 11px; line-height: 11px; padding: 5px 10px 6px; height: 11px; text-align: center; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; box-shadow: 0 1px 2px rgba(0,0,0,0.2); -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.2); -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.2); border: 1px solid #b2b2b2; border-top-color: #c9c9c9; border-bottom-color: #9a9a9a; background: url(../images/button_bg.png) repeat-x left top; } .minibutton:active { border-color: #aaa; box-shadow: 0 1px 2px #e4e4e4; -webkit-box-shadow: 0 1px 2px #e4e4e4; -moz-box-shadow: 0 1px 2px #e4e4e4; } .minibutton::selection { background: transparent; } .minibutton ::-moz-selection { background: transparent; } .minibutton.ok { color: #fff; background-image: url(../images/button_bg_green.gif); border-color: #4ba47c; border-top-color: #53b388; border-bottom-color: #459671; text-shadow: #aaa 0 -1px 0; } .minibutton.dark { border: 0; color: #fff; box-shadow: none; -webkit-box-shadow: none; -moz-box-shadow: none; background-image: url(../images/button_bg_dark.gif); text-shadow: none; } .minibutton.error { opacity: 0.5; color: #600; cursor: not-allowed; } 1.9.3~dfsg/documentation/css/tomorrow.css0000644000000000000000000000311412531364553017337 0ustar rootroot/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ /* Original code:; http://softwaremaniacs.org/media/soft/highlight/styles/tomorrow.css */ /* But forked for CoffeeScript */ .tomorrow-comment, pre .comment, pre .title { color: #8e908c; } .tomorrow-red, pre .variable, pre .tag, pre .regexp, pre .ruby .constant, pre .xml .tag .title, pre .xml .pi, pre .xml .doctype, pre .html .doctype, pre .css .id, pre .css .class, pre .css .pseudo { color: #c82829; } .tomorrow-orange, pre .number, pre .preprocessor, pre .built_in, pre .params, pre .constant { color: #000000; } .tomorrow-yellow, pre .class, pre .ruby .class .title, pre .css .rules .attribute { color: #eab700; } .tomorrow-green, pre .string, pre .value, pre .inheritance, pre .header, pre .ruby .symbol, pre .xml .cdata { color: #718c00; } .tomorrow-aqua, pre .css .hexcolor { color: #3e999f; } .tomorrow-blue, pre .function, pre .function .title, pre .python .decorator, pre .python .title, pre .ruby .function .title, pre .ruby .title .keyword, pre .perl .sub, pre .javascript .title, pre .coffeescript .title { color: #21439C; } .tomorrow-purple, pre .keyword, pre .reserved, pre .javascript .function { color: #FF5600; } pre .subst { color: #A535AE; } pre .literal { color: #A535AE; } pre .property { color: #A535AE; } pre .class .title { color: #21439C; } pre code { display: block; background: white; color: #000000; } pre .coffeescript .javascript, pre .javascript .xml, pre .tex .formula, pre .xml .javascript, pre .xml .vbscript, pre .xml .css, pre .xml .cdata { opacity: 0.5; } 1.9.3~dfsg/documentation/index.html.js0000644000000000000000000027057312531364553016574 0ustar rootroot CoffeeScript

CoffeeScript is a little language that compiles into JavaScript. Underneath that awkward Java-esque patina, JavaScript has always had a gorgeous heart. CoffeeScript is an attempt to expose the good parts of JavaScript in a simple way.

The golden rule of CoffeeScript is: "It's just JavaScript". The code compiles one-to-one into the equivalent JS, and there is no interpretation at runtime. You can use any existing JavaScript library seamlessly from CoffeeScript (and vice-versa). The compiled output is readable and pretty-printed, will work in every JavaScript runtime, and tends to run as fast or faster than the equivalent handwritten JavaScript.

Latest Version: 1.9.3

npm install -g coffee-script

Overview

CoffeeScript on the left, compiled JavaScript output on the right.

<%= codeFor('overview', 'cubes', false) %>

Installation

The CoffeeScript compiler is itself written in CoffeeScript, using the Jison parser generator. The command-line version of coffee is available as a Node.js utility. The core compiler however, does not depend on Node, and can be run in any JavaScript environment, or in the browser (see "Try CoffeeScript", above).

To install, first make sure you have a working copy of the latest stable version of Node.js. You can then install CoffeeScript globally with npm:

npm install -g coffee-script

When you need CoffeeScript as a dependency, install it locally:

npm install --save coffee-script

If you'd prefer to install the latest master version of CoffeeScript, you can clone the CoffeeScript source repository from GitHub, or download the source directly. To install the latest master CoffeeScript compiler with npm:

npm install -g jashkenas/coffeescript

Or, if you want to install to /usr/local, and don't want to use npm to manage it, open the coffee-script directory and run:

sudo bin/cake install

Usage

Once installed, you should have access to the coffee command, which can execute scripts, compile .coffee files into .js, and provide an interactive REPL. The coffee command takes the following options:

-c, --compile Compile a .coffee script into a .js JavaScript file of the same name.
-m, --map Generate source maps alongside the compiled JavaScript files. Adds sourceMappingURL directives to the JavaScript as well.
-i, --interactive Launch an interactive CoffeeScript session to try short snippets. Identical to calling coffee with no arguments.
-o, --output [DIR] Write out all compiled JavaScript files into the specified directory. Use in conjunction with --compile or --watch.
-j, --join [FILE] Before compiling, concatenate all scripts together in the order they were passed, and write them into the specified file. Useful for building large projects.
-w, --watch Watch files for changes, rerunning the specified command when any file is updated.
-p, --print Instead of writing out the JavaScript as a file, print it directly to stdout.
-s, --stdio Pipe in CoffeeScript to STDIN and get back JavaScript over STDOUT. Good for use with processes written in other languages. An example:
cat src/cake.coffee | coffee -sc
-l, --literate Parses the code as Literate CoffeeScript. You only need to specify this when passing in code directly over stdio, or using some sort of extension-less file name.
-e, --eval Compile and print a little snippet of CoffeeScript directly from the command line. For example:
coffee -e "console.log num for num in [10..1]"
-b, --bare Compile the JavaScript without the top-level function safety wrapper.
-t, --tokens Instead of parsing the CoffeeScript, just lex it, and print out the token stream: [IDENTIFIER square] [ASSIGN =] [PARAM_START (] ...
-n, --nodes Instead of compiling the CoffeeScript, just lex and parse it, and print out the parse tree:
Expressions
  Assign
    Value "square"
    Code "x"
      Op *
        Value "x"
        Value "x"
--nodejs The node executable has some useful options you can set, such as
--debug, --debug-brk, --max-stack-size, and --expose-gc. Use this flag to forward options directly to Node.js. To pass multiple flags, use --nodejs multiple times.

Examples:

  • Compile a directory tree of .coffee files in src into a parallel tree of .js files in lib:
    coffee --compile --output lib/ src/
  • Watch a file for changes, and recompile it every time the file is saved:
    coffee --watch --compile experimental.coffee
  • Concatenate a list of files into a single script:
    coffee --join project.js --compile src/*.coffee
  • Print out the compiled JS from a one-liner:
    coffee -bpe "alert i for i in [0..10]"
  • All together now, watch and recompile an entire project as you work on it:
    coffee -o lib/ -cw src/
  • Start the CoffeeScript REPL (Ctrl-D to exit, Ctrl-Vfor multi-line):
    coffee

Literate CoffeeScript

Besides being used as an ordinary programming language, CoffeeScript may also be written in "literate" mode. If you name your file with a .litcoffee extension, you can write it as a Markdown document — a document that also happens to be executable CoffeeScript code. The compiler will treat any indented blocks (Markdown's way of indicating source code) as code, and ignore the rest as comments.

Just for kicks, a little bit of the compiler is currently implemented in this fashion: See it as a document, raw, and properly highlighted in a text editor.

I'm fairly excited about this direction for the language, and am looking forward to writing (and more importantly, reading) more programs in this style. More information about Literate CoffeeScript, including an example program, are available in this blog post.

Language Reference

This reference is structured so that it can be read from top to bottom, if you like. Later sections use ideas and syntax previously introduced. Familiarity with JavaScript is assumed. In all of the following examples, the source CoffeeScript is provided on the left, and the direct compilation into JavaScript is on the right.

Many of the examples can be run (where it makes sense) by pressing the run button on the right, and can be loaded into the "Try CoffeeScript" console by pressing the load button on the left.

First, the basics: CoffeeScript uses significant whitespace to delimit blocks of code. You don't need to use semicolons ; to terminate expressions, ending the line will do just as well (although semicolons can still be used to fit multiple expressions onto a single line). Instead of using curly braces { } to surround blocks of code in functions, if-statements, switch, and try/catch, use indentation.

You don't need to use parentheses to invoke a function if you're passing arguments. The implicit call wraps forward to the end of the line or block expression.
console.log sys.inspect objectconsole.log(sys.inspect(object));

Functions Functions are defined by an optional list of parameters in parentheses, an arrow, and the function body. The empty function looks like this: ->

<%= codeFor('functions', 'cube(5)') %>

Functions may also have default values for arguments, which will be used if the incoming argument is missing (null or undefined).

<%= codeFor('default_args', 'fill("cup")') %>

Objects and Arrays The CoffeeScript literals for objects and arrays look very similar to their JavaScript cousins. When each property is listed on its own line, the commas are optional. Objects may be created using indentation instead of explicit braces, similar to YAML.

<%= codeFor('objects_and_arrays', 'song.join(" ... ")') %>

In JavaScript, you can't use reserved words, like class, as properties of an object, without quoting them as strings. CoffeeScript notices reserved words used as keys in objects and quotes them for you, so you don't have to worry about it (say, when using jQuery).

<%= codeFor('objects_reserved') %>

Lexical Scoping and Variable Safety The CoffeeScript compiler takes care to make sure that all of your variables are properly declared within lexical scope — you never need to write var yourself.

<%= codeFor('scope', 'inner') %>

Notice how all of the variable declarations have been pushed up to the top of the closest scope, the first time they appear. outer is not redeclared within the inner function, because it's already in scope; inner within the function, on the other hand, should not be able to change the value of the external variable of the same name, and therefore has a declaration of its own.

This behavior is effectively identical to Ruby's scope for local variables. Because you don't have direct access to the var keyword, it's impossible to shadow an outer variable on purpose, you may only refer to it. So be careful that you're not reusing the name of an external variable accidentally, if you're writing a deeply nested function.

Although suppressed within this documentation for clarity, all CoffeeScript output is wrapped in an anonymous function: (function(){ ... })(); This safety wrapper, combined with the automatic generation of the var keyword, make it exceedingly difficult to pollute the global namespace by accident.

If you'd like to create top-level variables for other scripts to use, attach them as properties on window, or on the exports object in CommonJS. The existential operator (covered below), gives you a reliable way to figure out where to add them; if you're targeting both CommonJS and the browser: exports ? this

If, Else, Unless, and Conditional Assignment If/else statements can be written without the use of parentheses and curly brackets. As with functions and other block expressions, multi-line conditionals are delimited by indentation. There's also a handy postfix form, with the if or unless at the end.

CoffeeScript can compile if statements into JavaScript expressions, using the ternary operator when possible, and closure wrapping otherwise. There is no explicit ternary statement in CoffeeScript — you simply use a regular if statement on a single line.

<%= codeFor('conditionals') %>

Splats... The JavaScript arguments object is a useful way to work with functions that accept variable numbers of arguments. CoffeeScript provides splats ..., both for function definition as well as invocation, making variable numbers of arguments a little bit more palatable.

<%= codeFor('splats', true) %>

Loops and Comprehensions Most of the loops you'll write in CoffeeScript will be comprehensions over arrays, objects, and ranges. Comprehensions replace (and compile into) for loops, with optional guard clauses and the value of the current array index. Unlike for loops, array comprehensions are expressions, and can be returned and assigned.

<%= codeFor('array_comprehensions') %>

Comprehensions should be able to handle most places where you otherwise would use a loop, each/forEach, map, or select/filter, for example: shortNames = (name for name in list when name.length < 5)
If you know the start and end of your loop, or would like to step through in fixed-size increments, you can use a range to specify the start and end of your comprehension.

<%= codeFor('range_comprehensions', 'countdown') %>

Note how because we are assigning the value of the comprehensions to a variable in the example above, CoffeeScript is collecting the result of each iteration into an array. Sometimes functions end with loops that are intended to run only for their side-effects. Be careful that you're not accidentally returning the results of the comprehension in these cases, by adding a meaningful return value — like true — or null, to the bottom of your function.

To step through a range comprehension in fixed-size chunks, use by, for example:
evens = (x for x in [0..10] by 2)

If you don't need the current iteration value you may omit it:
browser.closeCurrentTab() for [0...count]

Comprehensions can also be used to iterate over the keys and values in an object. Use of to signal comprehension over the properties of an object instead of the values in an array.

<%= codeFor('object_comprehensions', 'ages.join(", ")') %>

If you would like to iterate over just the keys that are defined on the object itself, by adding a hasOwnProperty check to avoid properties that may be inherited from the prototype, use
for own key, value of object

The only low-level loop that CoffeeScript provides is the while loop. The main difference from JavaScript is that the while loop can be used as an expression, returning an array containing the result of each iteration through the loop.

<%= codeFor('while', 'lyrics.join("\n")') %>

For readability, the until keyword is equivalent to while not, and the loop keyword is equivalent to while true.

When using a JavaScript loop to generate functions, it's common to insert a closure wrapper in order to ensure that loop variables are closed over, and all the generated functions don't just share the final values. CoffeeScript provides the do keyword, which immediately invokes a passed function, forwarding any arguments.

<%= codeFor('do') %>

Array Slicing and Splicing with Ranges Ranges can also be used to extract slices of arrays. With two dots (3..6), the range is inclusive (3, 4, 5, 6); with three dots (3...6), the range excludes the end (3, 4, 5). Slices indices have useful defaults. An omitted first index defaults to zero and an omitted second index defaults to the size of the array.

<%= codeFor('slices', 'middle') %>

The same syntax can be used with assignment to replace a segment of an array with new values, splicing it.

<%= codeFor('splices', 'numbers') %>

Note that JavaScript strings are immutable, and can't be spliced.

Everything is an Expression (at least, as much as possible) You might have noticed how even though we don't add return statements to CoffeeScript functions, they nonetheless return their final value. The CoffeeScript compiler tries to make sure that all statements in the language can be used as expressions. Watch how the return gets pushed down into each possible branch of execution in the function below.

<%= codeFor('expressions', 'eldest') %>

Even though functions will always return their final value, it's both possible and encouraged to return early from a function body writing out the explicit return (return value), when you know that you're done.

Because variable declarations occur at the top of scope, assignment can be used within expressions, even for variables that haven't been seen before:

<%= codeFor('expressions_assignment', 'six') %>

Things that would otherwise be statements in JavaScript, when used as part of an expression in CoffeeScript, are converted into expressions by wrapping them in a closure. This lets you do useful things, like assign the result of a comprehension to a variable:

<%= codeFor('expressions_comprehension', 'globals') %>

As well as silly things, like passing a try/catch statement directly into a function call:

<%= codeFor('expressions_try', true) %>

There are a handful of statements in JavaScript that can't be meaningfully converted into expressions, namely break, continue, and return. If you make use of them within a block of code, CoffeeScript won't try to perform the conversion.

Operators and Aliases Because the == operator frequently causes undesirable coercion, is intransitive, and has a different meaning than in other languages, CoffeeScript compiles == into ===, and != into !==. In addition, is compiles into ===, and isnt into !==.

You can use not as an alias for !.

For logic, and compiles to &&, and or into ||.

Instead of a newline or semicolon, then can be used to separate conditions from expressions, in while, if/else, and switch/when statements.

As in YAML, on and yes are the same as boolean true, while off and no are boolean false.

unless can be used as the inverse of if.

As a shortcut for this.property, you can use @property.

You can use in to test for array presence, and of to test for JavaScript object-key presence.

To simplify math expressions, ** can be used for exponentiation and // performs integer division. % works just like in JavaScript, while %% provides “dividend dependent modulo”:

<%= codeFor('modulo') %>

All together now:

CoffeeScriptJavaScript
is===
isnt!==
not!
and&&
or||
true, yes, ontrue
false, no, offfalse
@, thisthis
ofin
inno JS equivalent
a ** bMath.pow(a, b)
a // bMath.floor(a / b)
a %% b(a % b + b) % b
<%= codeFor('aliases') %>

The Existential Operator It's a little difficult to check for the existence of a variable in JavaScript. if (variable) ... comes close, but fails for zero, the empty string, and false. CoffeeScript's existential operator ? returns true unless a variable is null or undefined, which makes it analogous to Ruby's nil?

It can also be used for safer conditional assignment than ||= provides, for cases where you may be handling numbers or strings.

<%= codeFor('existence', 'footprints') %>

The accessor variant of the existential operator ?. can be used to soak up null references in a chain of properties. Use it instead of the dot accessor . in cases where the base value may be null or undefined. If all of the properties exist then you'll get the expected result, if the chain is broken, undefined is returned instead of the TypeError that would be raised otherwise.

<%= codeFor('soaks') %>

Soaking up nulls is similar to Ruby's andand gem, and to the safe navigation operator in Groovy.

Classes, Inheritance, and Super JavaScript's prototypal inheritance has always been a bit of a brain-bender, with a whole family tree of libraries that provide a cleaner syntax for classical inheritance on top of JavaScript's prototypes: Base2, Prototype.js, JS.Class, etc. The libraries provide syntactic sugar, but the built-in inheritance would be completely usable if it weren't for a couple of small exceptions: it's awkward to call super (the prototype object's implementation of the current function), and it's awkward to correctly set the prototype chain.

Instead of repetitively attaching functions to a prototype, CoffeeScript provides a basic class structure that allows you to name your class, set the superclass, assign prototypal properties, and define the constructor, in a single assignable expression.

Constructor functions are named, to better support helpful stack traces. In the first class in the example below, this.constructor.name is "Animal".

<%= codeFor('classes', true) %>

If structuring your prototypes classically isn't your cup of tea, CoffeeScript provides a couple of lower-level conveniences. The extends operator helps with proper prototype setup, and can be used to create an inheritance chain between any pair of constructor functions; :: gives you quick access to an object's prototype; and super() is converted into a call against the immediate ancestor's method of the same name.

<%= codeFor('prototypes', '"one_two".dasherize()') %>

Finally, class definitions are blocks of executable code, which make for interesting metaprogramming possibilities. Because in the context of a class definition, this is the class object itself (the constructor function), you can assign static properties by using
@property: value, and call functions defined in parent classes: @attr 'title', type: 'text'

Destructuring Assignment To make extracting values from complex arrays and objects more convenient, CoffeeScript implements ECMAScript Harmony's proposed destructuring assignment syntax. When you assign an array or object literal to a value, CoffeeScript breaks up and matches both sides against each other, assigning the values on the right to the variables on the left. In the simplest case, it can be used for parallel assignment:

<%= codeFor('parallel_assignment', 'theBait') %>

But it's also helpful for dealing with functions that return multiple values.

<%= codeFor('multiple_return_values', 'forecast') %>

Destructuring assignment can be used with any depth of array and object nesting, to help pull out deeply nested properties.

<%= codeFor('object_extraction', 'name + "-" + street') %>

Destructuring assignment can even be combined with splats.

<%= codeFor('patterns_and_splats', 'contents.join("")') %>

Expansion can be used to retrieve elements from the end of an array without having to assign the rest of its values. It works in function parameter lists as well.

<%= codeFor('expansion', 'first + " " + last') %>

Destructuring assignment is also useful when combined with class constructors to assign properties to your instance from an options object passed to the constructor.

<%= codeFor('constructor_destructuring', 'tim.age') %>

Bound Functions, Generator Functions In JavaScript, the this keyword is dynamically scoped to mean the object that the current function is attached to. If you pass a function as a callback or attach it to a different object, the original value of this will be lost. If you're not familiar with this behavior, this Digital Web article gives a good overview of the quirks.

The fat arrow => can be used to both define a function, and to bind it to the current value of this, right on the spot. This is helpful when using callback-based libraries like Prototype or jQuery, for creating iterator functions to pass to each, or event-handler functions to use with on. Functions created with the fat arrow are able to access properties of the this where they're defined.

<%= codeFor('fat_arrow') %>

If we had used -> in the callback above, @customer would have referred to the undefined "customer" property of the DOM element, and trying to call purchase() on it would have raised an exception.

When used in a class definition, methods declared with the fat arrow will be automatically bound to each instance of the class when the instance is constructed.

CoffeeScript functions also support ES6 generator functions through the yield keyword. There's no function*(){} nonsense — a generator in CoffeeScript is simply a function that yields.

<%= codeFor('generators', 'ps.next().value') %>

yield* is called yield from, and yield return may be used if you need to force a generator that doesn't yield.

Embedded JavaScript Hopefully, you'll never need to use it, but if you ever need to intersperse snippets of JavaScript within your CoffeeScript, you can use backticks to pass it straight through.

<%= codeFor('embedded', 'hi()') %>

Switch/When/Else Switch statements in JavaScript are a bit awkward. You need to remember to break at the end of every case statement to avoid accidentally falling through to the default case. CoffeeScript prevents accidental fall-through, and can convert the switch into a returnable, assignable expression. The format is: switch condition, when clauses, else the default case.

As in Ruby, switch statements in CoffeeScript can take multiple values for each when clause. If any of the values match, the clause runs.

<%= codeFor('switch') %>

Switch statements can also be used without a control expression, turning them in to a cleaner alternative to if/else chains.

<%= codeFor('switch_with_no_expression') %>

Try/Catch/Finally Try-expressions have the same semantics as try-statements in JavaScript, though in CoffeeScript, you may omit both the catch and finally parts. The catch part may also omit the error parameter if it is not needed.

<%= codeFor('try') %>

Chained Comparisons CoffeeScript borrows chained comparisons from Python — making it easy to test if a value falls within a certain range.

<%= codeFor('comparisons', 'healthy') %>

String Interpolation, Block Strings, and Block Comments Ruby-style string interpolation is included in CoffeeScript. Double-quoted strings allow for interpolated values, using #{ ... }, and single-quoted strings are literal. You may even use interpolation in object keys.

<%= codeFor('interpolation', 'sentence') %>

Multiline strings are allowed in CoffeeScript. Lines are joined by a single space unless they end with a backslash. Indentation is ignored.

<%= codeFor('strings', 'mobyDick') %>

Block strings can be used to hold formatted or indentation-sensitive text (or, if you just don't feel like escaping quotes and apostrophes). The indentation level that begins the block is maintained throughout, so you can keep it all aligned with the body of your code.

<%= codeFor('heredocs', 'html') %>

Double-quoted block strings, like other double-quoted strings, allow interpolation.

Sometimes you'd like to pass a block comment through to the generated JavaScript. For example, when you need to embed a licensing header at the top of a file. Block comments, which mirror the syntax for block strings, are preserved in the generated code.

<%= codeFor('block_comment') %>

Block Regular Expressions Similar to block strings and comments, CoffeeScript supports block regexes — extended regular expressions that ignore internal whitespace and can contain comments and interpolation. Modeled after Perl's /x modifier, CoffeeScript's block regexes are delimited by /// and go a long way towards making complex regular expressions readable. To quote from the CoffeeScript source:

<%= codeFor('heregexes') %>

Cake, and Cakefiles

CoffeeScript includes a (very) simple build system similar to Make and Rake. Naturally, it's called Cake, and is used for the tasks that build and test the CoffeeScript language itself. Tasks are defined in a file named Cakefile, and can be invoked by running cake [task] from within the directory. To print a list of all the tasks and options, just type cake.

Task definitions are written in CoffeeScript, so you can put arbitrary code in your Cakefile. Define a task with a name, a long description, and the function to invoke when the task is run. If your task takes a command-line option, you can define the option with short and long flags, and it will be made available in the options object. Here's a task that uses the Node.js API to rebuild CoffeeScript's parser:

<%= codeFor('cake_tasks') %>

If you need to invoke one task before another — for example, running build before test, you can use the invoke function: invoke 'build'. Cake tasks are a minimal way to expose your CoffeeScript functions to the command line, so don't expect any fanciness built-in. If you need dependencies, or async callbacks, it's best to put them in your code itself — not the cake task.

Source Maps

CoffeeScript 1.6.1 and above include support for generating source maps, a way to tell your JavaScript engine what part of your CoffeeScript program matches up with the code being evaluated. Browsers that support it can automatically use source maps to show your original source code in the debugger. To generate source maps alongside your JavaScript files, pass the --map or -m flag to the compiler.

For a full introduction to source maps, how they work, and how to hook them up in your browser, read the HTML5 Tutorial.

"text/coffeescript" Script Tags

While it's not recommended for serious use, CoffeeScripts may be included directly within the browser using <script type="text/coffeescript"> tags. The source includes a compressed and minified version of the compiler (Download current version here, 39k when gzipped) as extras/coffee-script.js. Include this file on a page with inline CoffeeScript tags, and it will compile and evaluate them in order.

In fact, the little bit of glue script that runs "Try CoffeeScript" above, as well as the jQuery for the menu, is implemented in just this way. View source and look at the bottom of the page to see the example. Including the script also gives you access to CoffeeScript.compile() so you can pop open Firebug and try compiling some strings.

The usual caveats about CoffeeScript apply — your inline scripts will run within a closure wrapper, so if you want to expose global variables or functions, attach them to the window object.

Books

There are a number of excellent resources to help you get started with CoffeeScript, some of which are freely available online.

Screencasts

  • A Sip of CoffeeScript is a Code School Course which combines 6 screencasts with in-browser coding to make learning fun. The first level is free to try out.
  • Meet CoffeeScript is a 75-minute long screencast by PeepCode. Highly memorable for its animations which demonstrate transforming CoffeeScript into the equivalent JS.
  • If you're looking for less of a time commitment, RailsCasts' CoffeeScript Basics should have you covered, hitting all of the important notes about CoffeeScript in 11 minutes.

Examples

The best list of open-source CoffeeScript examples can be found on GitHub. But just to throw out few more:

  • github's Hubot, a friendly IRC robot that can perform any number of useful and useless tasks.
  • sstephenson's Pow, a zero-configuration Rack server, with comprehensive annotated source.
  • technoweenie's Coffee-Resque, a port of Resque for Node.js.
  • assaf's Zombie.js, a headless, full-stack, faux-browser testing library for Node.js.
  • jashkenas' Underscore.coffee, a port of the Underscore.js library of helper functions.
  • stephank's Orona, a remake of the Bolo tank game for modern browsers.
  • github's Atom, a hackable text editor built on web technologies.

Resources

  • Source Code
    Use bin/coffee to test your changes,
    bin/cake test to run the test suite,
    bin/cake build to rebuild the CoffeeScript compiler, and
    bin/cake build:parser to regenerate the Jison parser if you're working on the grammar.

    git checkout lib && bin/cake build:full is a good command to run when you're working on the core language. It'll refresh the lib directory (in case you broke something), build your altered compiler, use that to rebuild itself (a good sanity test) and then run all of the tests. If they pass, there's a good chance you've made a successful change.
  • CoffeeScript Issues
    Bug reports, feature proposals, and ideas for changes to the language belong here.
  • CoffeeScript Google Group
    If you'd like to ask a question, the mailing list is a good place to get help.
  • The CoffeeScript Wiki
    If you've ever learned a neat CoffeeScript tip or trick, or ran into a gotcha — share it on the wiki. The wiki also serves as a directory of handy text editor extensions, web framework plugins, and general CoffeeScript build tools.
  • The FAQ
    Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
  • JS2Coffee
    Is a very well done reverse JavaScript-to-CoffeeScript compiler. It's not going to be perfect (infer what your JavaScript classes are, when you need bound functions, and so on...) — but it's a great starting point for converting simple scripts.
  • High-Rez Logo
    The CoffeeScript logo is available in Illustrator, EPS and PSD formats, for use in presentations.

Web Chat (IRC)

Quick help and advice can usually be found in the CoffeeScript IRC room. Join #coffeescript on irc.freenode.net, or click the button below to open a webchat session on this page.

Change Log

<%= releaseHeader('2015-05-14', '1.9.3', '1.9.2') %>

  • Bugfix for interpolation in the first key of an object literal in an implicit call.
  • Fixed broken error messages in the REPL, as well as a few minor bugs with the REPL.
  • Fixed source mappings for tokens at the beginning of lines when compiling with the --bare option. This has the nice side effect of generating smaller source maps.
  • Slight formatting improvement of compiled block comments.
  • Better error messages for on, off, yes and no.

<%= releaseHeader('2015-04-15', '1.9.2', '1.9.1') %>

  • Fixed a watch mode error introduced in 1.9.1 when compiling multiple files with the same filename.
  • Bugfix for yield around expressions containing this.
  • Added a Ruby-style -r option to the REPL, which allows requiring a module before execution with --eval or --interactive.
  • In <script type="text/coffeescript"> tags, to avoid possible duplicate browser requests for .coffee files, you can now use the data-src attribute instead of src.
  • Minor bug fixes for IE8, strict ES5 regular expressions and Browserify.

<%= releaseHeader('2015-02-18', '1.9.1', '1.9.0') %>

  • Interpolation now works in object literal keys (again). You can use this to dynamically name properties.
  • Internal compiler variable names no longer start with underscores. This makes the generated JavaScript a bit prettier, and also fixes an issue with the completely broken and ungodly way that AngularJS "parses" function arguments.
  • Fixed a few yield-related edge cases with yield return and yield throw.
  • Minor bug fixes and various improvements to compiler error messages.

<%= releaseHeader('2015-01-29', '1.9.0', '1.8.0') %>

  • CoffeeScript now supports ES6 generators. A generator is simply a function that yields.
  • More robust parsing and improved error messages for strings and regexes — especially with respect to interpolation.
  • Changed strategy for the generation of internal compiler variable names. Note that this means that @example function parameters are no longer available as naked example variables within the function body.
  • Fixed REPL compatibility with latest versions of Node and Io.js.
  • Various minor bug fixes.

<%= releaseHeader('2014-08-26', '1.8.0', '1.7.1') %>

  • The --join option of the CLI is now deprecated.
  • Source maps now use .js.map as file extension, instead of just .map.
  • The CLI now exits with the exit code 1 when it fails to write a file to disk.
  • The compiler no longer crashes on unterminated, single-quoted strings.
  • Fixed location data for string interpolations, which made source maps out of sync.
  • The error marker in error messages is now correctly positioned if the code is indented with tabs.
  • Fixed a slight formatting error in CoffeeScript’s source map-patched stack traces.
  • The %% operator now coerces its right operand only once.
  • It is now possible to require CoffeeScript files from Cakefiles without having to register the compiler first.
  • The CoffeeScript REPL is now exported and can be required using require 'coffee-script/repl'.
  • Fixes for the REPL in Node 0.11.

<%= releaseHeader('2014-01-29', '1.7.1', '1.7.0') %>

  • Fixed a typo that broke node module lookup when running a script directly with the coffee binary.

<%= releaseHeader('2014-01-28', '1.7.0', '1.6.3') %>

  • When requiring CoffeeScript files in Node you must now explicitly register the compiler. This can be done with require 'coffee-script/register' or CoffeeScript.register(). Also for configuration such as Mocha's, use coffee-script/register.
  • Improved error messages, source maps and stack traces. Source maps now use the updated //# syntax.
  • Leading . now closes all open calls, allowing for simpler chaining syntax.
<%= codeFor('chaining') %>
  • Added **, // and %% operators and ... expansion in parameter lists and destructuring expressions.
  • Multiline strings are now joined by a single space and ignore all indentation. A backslash at the end of a line can denote the amount of whitespace between lines, in both strings and heredocs. Backslashes correctly escape whitespace in block regexes.
  • Closing brackets can now be indented and therefore no longer cause unexpected error.
  • Several breaking compilation fixes. Non-callable literals (strings, numbers etc.) don't compile in a call now and multiple postfix conditionals compile properly. Postfix conditionals and loops always bind object literals. Conditional assignment compiles properly in subexpressions. super is disallowed outside of methods and works correctly inside for loops.
  • Formatting of compiled block comments has been improved.
  • No more -p folders on Windows.
  • The options object passed to CoffeeScript is no longer mutated.

<%= releaseHeader('2013-06-02', '1.6.3', '1.6.2') %>

  • The CoffeeScript REPL now remembers your history between sessions. Just like a proper REPL should.
  • You can now use require in Node to load .coffee.md Literate CoffeeScript files. In the browser, text/literate-coffeescript script tags.
  • The old coffee --lint command has been removed. It was useful while originally working on the compiler, but has been surpassed by JSHint. You may now use -l to pass literate files in over stdio.
  • Bugfixes for Windows path separators, catch without naming the error, and executable-class-bodies-with- prototypal-property-attachment.

<%= releaseHeader('2013-03-18', '1.6.2', '1.6.1') %>

  • Source maps have been used to provide automatic line-mapping when running CoffeeScript directly via the coffee command, and for automatic line-mapping when running CoffeeScript directly in the browser. Also, to provide better error messages for semantic errors thrown by the compiler — with colors, even.
  • Improved support for mixed literate/vanilla-style CoffeeScript projects, and generating source maps for both at the same time.
  • Fixes for 1.6.x regressions with overriding inherited bound functions, and for Windows file path management.
  • The coffee command can now correctly fork() both .coffee and .js files. (Requires Node.js 0.9+)

<%= releaseHeader('2013-03-05', '1.6.1', '1.5.0') %>

  • First release of source maps. Pass the --map flag to the compiler, and off you go. Direct all your thanks over to Jason Walton.
  • Fixed a 1.5.0 regression with multiple implicit calls against an indented implicit object. Combinations of implicit function calls and implicit objects should generally be parsed better now — but it still isn't good style to nest them too heavily.
  • .coffee.md is now also supported as a Literate CoffeeScript file extension, for existing tooling. .litcoffee remains the canonical one.
  • Several minor fixes surrounding member properties, bound methods and super in class declarations.

<%= releaseHeader('2013-02-25', '1.5.0', '1.4.0') %>

  • First release of Literate CoffeeScript.
  • The CoffeeScript REPL is now based on the Node.js REPL, and should work better and more familiarly.
  • Returning explicit values from constructors is now forbidden. If you want to return an arbitrary value, use a function, not a constructor.
  • You can now loop over an array backwards, without having to manually deal with the indexes: for item in list by -1
  • Source locations are now preserved in the CoffeeScript AST, although source maps are not yet being emitted.

<%= releaseHeader('2012-10-23', '1.4.0', '1.3.3') %>

  • The CoffeeScript compiler now strips Microsoft's UTF-8 BOM if it exists, allowing you to compile BOM-borked source files.
  • Fix Node/compiler deprecation warnings by removing registerExtension, and moving from path.exists to fs.exists.
  • Small tweaks to splat compilation, backticks, slicing, and the error for duplicate keys in object literals.

<%= releaseHeader('2012-05-15', '1.3.3', '1.3.1') %>

  • Due to the new semantics of JavaScript's strict mode, CoffeeScript no longer guarantees that constructor functions have names in all runtimes. See #2052 for discussion.
  • Inside of a nested function inside of an instance method, it's now possible to call super more reliably (walks recursively up).
  • Named loop variables no longer have different scoping heuristics than other local variables. (Reverts #643)
  • Fix for splats nested within the LHS of destructuring assignment.
  • Corrections to our compile time strict mode forbidding of octal literals.

<%= releaseHeader('2012-04-10', '1.3.1', '1.2.0') %>

  • CoffeeScript now enforces all of JavaScript's Strict Mode early syntax errors at compile time. This includes old-style octal literals, duplicate property names in object literals, duplicate parameters in a function definition, deleting naked variables, setting the value of eval or arguments, and more. See a full discussion at #1547.
  • The REPL now has a handy new multi-line mode for entering large blocks of code. It's useful when copy-and-pasting examples into the REPL. Enter multi-line mode with Ctrl-V. You may also now pipe input directly into the REPL.
  • CoffeeScript now prints a Generated by CoffeeScript VERSION header at the top of each compiled file.
  • Conditional assignment of previously undefined variables a or= b is now considered a syntax error.
  • A tweak to the semantics of do, which can now be used to more easily simulate a namespace: do (x = 1, y = 2) -> ...
  • Loop indices are now mutable within a loop iteration, and immutable between them.
  • Both endpoints of a slice are now allowed to be omitted for consistency, effectively creating a shallow copy of the list.
  • Additional tweaks and improvements to coffee --watch under Node's "new" file watching API. Watch will now beep by default if you introduce a syntax error into a watched script. We also now ignore hidden directories by default when watching recursively.

<%= releaseHeader('2011-12-18', '1.2.0', '1.1.3') %>

  • Multiple improvements to coffee --watch and --join. You may now use both together, as well as add and remove files and directories within a --watch'd folder.
  • The throw statement can now be used as part of an expression.
  • Block comments at the top of the file will now appear outside of the safety closure wrapper.
  • Fixed a number of minor 1.1.3 regressions having to do with trailing operators and unfinished lines, and a more major 1.1.3 regression that caused bound functions within bound class functions to have the incorrect this.

<%= releaseHeader('2011-11-08', '1.1.3', '1.1.2') %>

  • Ahh, whitespace. CoffeeScript's compiled JS now tries to space things out and keep it readable, as you can see in the examples on this page.
  • You can now call super in class level methods in class bodies, and bound class methods now preserve their correct context.
  • JavaScript has always supported octal numbers 010 is 8, and hexadecimal numbers 0xf is 15, but CoffeeScript now also supports binary numbers: 0b10 is 2.
  • The CoffeeScript module has been nested under a subdirectory to make it easier to require individual components separately, without having to use npm. For example, after adding the CoffeeScript folder to your path: require('coffee-script/lexer')
  • There's a new "link" feature in Try CoffeeScript on this webpage. Use it to get a shareable permalink for your example script.
  • The coffee --watch feature now only works on Node.js 0.6.0 and higher, but now also works properly on Windows.
  • Lots of small bug fixes from @michaelficarra, @geraldalewis, @satyr, and @trevorburnham.

<%= releaseHeader('2011-08-04', '1.1.2', '1.1.1') %> Fixes for block comment formatting, ?= compilation, implicit calls against control structures, implicit invocation of a try/catch block, variadic arguments leaking from local scope, line numbers in syntax errors following heregexes, property access on parenthesized number literals, bound class methods and super with reserved names, a REPL overhaul, consecutive compiled semicolons, block comments in implicitly called objects, and a Chrome bug.

<%= releaseHeader('2011-05-10', '1.1.1', '1.1.0') %> Bugfix release for classes with external constructor functions, see issue #1182.

<%= releaseHeader('2011-05-01', '1.1.0', '1.0.1') %> When running via the coffee executable, process.argv and friends now report coffee instead of node. Better compatibility with Node.js 0.4.x module lookup changes. The output in the REPL is now colorized, like Node's is. Giving your concatenated CoffeeScripts a name when using --join is now mandatory. Fix for lexing compound division /= as a regex accidentally. All text/coffeescript tags should now execute in the order they're included. Fixed an issue with extended subclasses using external constructor functions. Fixed an edge-case infinite loop in addImplicitParentheses. Fixed exponential slowdown with long chains of function calls. Globals no longer leak into the CoffeeScript REPL. Splatted parameters are declared local to the function.

<%= releaseHeader('2011-01-31', '1.0.1', '1.0.0') %> Fixed a lexer bug with Unicode identifiers. Updated REPL for compatibility with Node.js 0.3.7. Fixed requiring relative paths in the REPL. Trailing return and return undefined are now optimized away. Stopped requiring the core Node.js "util" module for back-compatibility with Node.js 0.2.5. Fixed a case where a conditional return would cause fallthrough in a switch statement. Optimized empty objects in destructuring assignment.

<%= releaseHeader('2010-12-24', '1.0.0', '0.9.6') %> CoffeeScript loops no longer try to preserve block scope when functions are being generated within the loop body. Instead, you can use the do keyword to create a convenient closure wrapper. Added a --nodejs flag for passing through options directly to the node executable. Better behavior around the use of pure statements within expressions. Fixed inclusive slicing through -1, for all browsers, and splicing with arbitrary expressions as endpoints.

<%= releaseHeader('2010-12-06', '0.9.6', '0.9.5') %> The REPL now properly formats stacktraces, and stays alive through asynchronous exceptions. Using --watch now prints timestamps as files are compiled. Fixed some accidentally-leaking variables within plucked closure-loops. Constructors now maintain their declaration location within a class body. Dynamic object keys were removed. Nested classes are now supported. Fixes execution context for naked splatted functions. Bugfix for inversion of chained comparisons. Chained class instantiation now works properly with splats.

<%= releaseHeader('2010-11-21', '0.9.5', '0.9.4') %> 0.9.5 should be considered the first release candidate for CoffeeScript 1.0. There have been a large number of internal changes since the previous release, many contributed from satyr's Coco dialect of CoffeeScript. Heregexes (extended regexes) were added. Functions can now have default arguments. Class bodies are now executable code. Improved syntax errors for invalid CoffeeScript. undefined now works like null, and cannot be assigned a new value. There was a precedence change with respect to single-line comprehensions: result = i for i in list
used to parse as result = (i for i in list) by default ... it now parses as
(result = i) for i in list.

<%= releaseHeader('2010-09-21', '0.9.4', '0.9.3') %> CoffeeScript now uses appropriately-named temporary variables, and recycles their references after use. Added require.extensions support for Node.js 0.3. Loading CoffeeScript in the browser now adds just a single CoffeeScript object to global scope. Fixes for implicit object and block comment edge cases.

<%= releaseHeader('2010-09-16', '0.9.3', '0.9.2') %> CoffeeScript switch statements now compile into JS switch statements — they previously compiled into if/else chains for JavaScript 1.3 compatibility. Soaking a function invocation is now supported. Users of the RubyMine editor should now be able to use --watch mode.

<%= releaseHeader('2010-08-23', '0.9.2', '0.9.1') %> Specifying the start and end of a range literal is now optional, eg. array[3..]. You can now say a not instanceof b. Fixed important bugs with nested significant and non-significant indentation (Issue #637). Added a --require flag that allows you to hook into the coffee command. Added a custom jsl.conf file for our preferred JavaScriptLint setup. Sped up Jison grammar compilation time by flattening rules for operations. Block comments can now be used with JavaScript-minifier-friendly syntax. Added JavaScript's compound assignment bitwise operators. Bugfixes to implicit object literals with leading number and string keys, as the subject of implicit calls, and as part of compound assignment.

<%= releaseHeader('2010-08-11', '0.9.1', '0.9.0') %> Bugfix release for 0.9.1. Greatly improves the handling of mixed implicit objects, implicit function calls, and implicit indentation. String and regex interpolation is now strictly #{ ... } (Ruby style). The compiler now takes a --require flag, which specifies scripts to run before compilation.

<%= releaseHeader('2010-08-04', '0.9.0', '0.7.2') %> The CoffeeScript 0.9 series is considered to be a release candidate for 1.0; let's give her a shakedown cruise. 0.9.0 introduces a massive backwards-incompatible change: Assignment now uses =, and object literals use :, as in JavaScript. This allows us to have implicit object literals, and YAML-style object definitions. Half assignments are removed, in favor of +=, or=, and friends. Interpolation now uses a hash mark # instead of the dollar sign $ — because dollar signs may be part of a valid JS identifier. Downwards range comprehensions are now safe again, and are optimized to straight for loops when created with integer endpoints. A fast, unguarded form of object comprehension was added: for all key, value of object. Mentioning the super keyword with no arguments now forwards all arguments passed to the function, as in Ruby. If you extend class B from parent class A, if A has an extended method defined, it will be called, passing in B — this enables static inheritance, among other things. Cleaner output for functions bound with the fat arrow. @variables can now be used in parameter lists, with the parameter being automatically set as a property on the object — useful in constructors and setter functions. Constructor functions can now take splats.

<%= releaseHeader('2010-07-12', '0.7.2', '0.7.1') %> Quick bugfix (right after 0.7.1) for a problem that prevented coffee command-line options from being parsed in some circumstances.

<%= releaseHeader('2010-07-11', '0.7.1', '0.7.0') %> Block-style comments are now passed through and printed as JavaScript block comments -- making them useful for licenses and copyright headers. Better support for running coffee scripts standalone via hashbangs. Improved syntax errors for tokens that are not in the grammar.

<%= releaseHeader('2010-06-28', '0.7.0', '0.6.2') %> Official CoffeeScript variable style is now camelCase, as in JavaScript. Reserved words are now allowed as object keys, and will be quoted for you. Range comprehensions now generate cleaner code, but you have to specify by -1 if you'd like to iterate downward. Reporting of syntax errors is greatly improved from the previous release. Running coffee with no arguments now launches the REPL, with Readline support. The <- bind operator has been removed from CoffeeScript. The loop keyword was added, which is equivalent to a while true loop. Comprehensions that contain closures will now close over their variables, like the semantics of a forEach. You can now use bound function in class definitions (bound to the instance). For consistency, a in b is now an array presence check, and a of b is an object-key check. Comments are no longer passed through to the generated JavaScript.

<%= releaseHeader('2010-05-15', '0.6.2', '0.6.1') %> The coffee command will now preserve directory structure when compiling a directory full of scripts. Fixed two omissions that were preventing the CoffeeScript compiler from running live within Internet Explorer. There's now a syntax for block comments, similar in spirit to CoffeeScript's heredocs. ECMA Harmony DRY-style pattern matching is now supported, where the name of the property is the same as the name of the value: {name, length}: func. Pattern matching is now allowed within comprehension variables. unless is now allowed in block form. until loops were added, as the inverse of while loops. switch statements are now allowed without switch object clauses. Compatible with Node.js v0.1.95.

<%= releaseHeader('2010-04-12', '0.6.1', '0.6.0') %> Upgraded CoffeeScript for compatibility with the new Node.js v0.1.90 series.

<%= releaseHeader('2010-04-03', '0.6.0', '0.5.6') %> Trailing commas are now allowed, a-la Python. Static properties may be assigned directly within class definitions, using @property notation.

<%= releaseHeader('2010-03-23', '0.5.6', '0.5.5') %> Interpolation can now be used within regular expressions and heredocs, as well as strings. Added the <- bind operator. Allowing assignment to half-expressions instead of special ||=-style operators. The arguments object is no longer automatically converted into an array. After requiring coffee-script, Node.js can now directly load .coffee files, thanks to registerExtension. Multiple splats can now be used in function calls, arrays, and pattern matching.

<%= releaseHeader('2010-03-08', '0.5.5', '0.5.4') %> String interpolation, contributed by Stan Angeloff. Since --run has been the default since 0.5.3, updating --stdio and --eval to run by default, pass --compile as well if you'd like to print the result.

<%= releaseHeader('2010-03-03', '0.5.4', '0.5.3') %> Bugfix that corrects the Node.js global constants __filename and __dirname. Tweaks for more flexible parsing of nested function literals and improperly-indented comments. Updates for the latest Node.js API.

<%= releaseHeader('2010-02-27', '0.5.3', '0.5.2') %> CoffeeScript now has a syntax for defining classes. Many of the core components (Nodes, Lexer, Rewriter, Scope, Optparse) are using them. Cakefiles can use optparse.coffee to define options for tasks. --run is now the default flag for the coffee command, use --compile to save JavaScripts. Bugfix for an ambiguity between RegExp literals and chained divisions.

<%= releaseHeader('2010-02-25', '0.5.2', '0.5.1') %> Added a compressed version of the compiler for inclusion in web pages as
extras/coffee-script.js. It'll automatically run any script tags with type text/coffeescript for you. Added a --stdio option to the coffee command, for piped-in compiles.

<%= releaseHeader('2010-02-24', '0.5.1', '0.5.0') %> Improvements to null soaking with the existential operator, including soaks on indexed properties. Added conditions to while loops, so you can use them as filters with when, in the same manner as comprehensions.

<%= releaseHeader('2010-02-21', '0.5.0', '0.3.2') %> CoffeeScript 0.5.0 is a major release, While there are no language changes, the Ruby compiler has been removed in favor of a self-hosting compiler written in pure CoffeeScript.

<%= releaseHeader('2010-02-08', '0.3.2', '0.3.0') %> @property is now a shorthand for this.property.
Switched the default JavaScript engine from Narwhal to Node.js. Pass the --narwhal flag if you'd like to continue using it.

<%= releaseHeader('2010-01-26', '0.3.0', '0.2.6') %> CoffeeScript 0.3 includes major syntax changes:
The function symbol was changed to ->, and the bound function symbol is now =>.
Parameter lists in function definitions must now be wrapped in parentheses.
Added property soaking, with the ?. operator.
Made parentheses optional, when invoking functions with arguments.
Removed the obsolete block literal syntax.

<%= releaseHeader('2010-01-17', '0.2.6', '0.2.5') %> Added Python-style chained comparisons, the conditional existence operator ?=, and some examples from Beautiful Code. Bugfixes relating to statement-to-expression conversion, arguments-to-array conversion, and the TextMate syntax highlighter.

<%= releaseHeader('2010-01-13', '0.2.5', '0.2.4') %> The conditions in switch statements can now take multiple values at once — If any of them are true, the case will run. Added the long arrow ==>, which defines and immediately binds a function to this. While loops can now be used as expressions, in the same way that comprehensions can. Splats can be used within pattern matches to soak up the rest of an array.

<%= releaseHeader('2010-01-12', '0.2.4', '0.2.3') %> Added ECMAScript Harmony style destructuring assignment, for dealing with extracting values from nested arrays and objects. Added indentation-sensitive heredocs for nicely formatted strings or chunks of code.

<%= releaseHeader('2010-01-11', '0.2.3', '0.2.2') %> Axed the unsatisfactory ino keyword, replacing it with of for object comprehensions. They now look like: for prop, value of object.

<%= releaseHeader('2010-01-10', '0.2.2', '0.2.1') %> When performing a comprehension over an object, use ino, instead of in, which helps us generate smaller, more efficient code at compile time.
Added :: as a shorthand for saying .prototype.
The "splat" symbol has been changed from a prefix asterisk *, to a postfix ellipsis ...
Added JavaScript's in operator, empty return statements, and empty while loops.
Constructor functions that start with capital letters now include a safety check to make sure that the new instance of the object is returned.
The extends keyword now functions identically to goog.inherits in Google's Closure Library.

<%= releaseHeader('2010-01-05', '0.2.1', '0.2.0') %> Arguments objects are now converted into real arrays when referenced.

<%= releaseHeader('2010-01-05', '0.2.0', '0.1.6') %> Major release. Significant whitespace. Better statement-to-expression conversion. Splats. Splice literals. Object comprehensions. Blocks. The existential operator. Many thanks to all the folks who posted issues, with special thanks to Liam O'Connor-Davis for whitespace and expression help.

<%= releaseHeader('2009-12-27', '0.1.6', '0.1.5') %> Bugfix for running coffee --interactive and --run from outside of the CoffeeScript directory. Bugfix for nested function/if-statements.

<%= releaseHeader('2009-12-26', '0.1.5', '0.1.4') %> Array slice literals and array comprehensions can now both take Ruby-style ranges to specify the start and end. JavaScript variable declaration is now pushed up to the top of the scope, making all assignment statements into expressions. You can use \ to escape newlines. The coffee-script command is now called coffee.

<%= releaseHeader('2009-12-25', '0.1.4', '0.1.3') %> The official CoffeeScript extension is now .coffee instead of .cs, which properly belongs to C#. Due to popular demand, you can now also use = to assign. Unlike JavaScript, = can also be used within object literals, interchangeably with :. Made a grammatical fix for chained function calls like func(1)(2)(3)(4). Inheritance and super no longer use __proto__, so they should be IE-compatible now.

<%= releaseHeader('2009-12-25', '0.1.3', '0.1.2') %> The coffee command now includes --interactive, which launches an interactive CoffeeScript session, and --run, which directly compiles and executes a script. Both options depend on a working installation of Narwhal. The aint keyword has been replaced by isnt, which goes together a little smoother with is. Quoted strings are now allowed as identifiers within object literals: eg. {"5+5": 10}. All assignment operators now use a colon: +:, -:, *:, etc.

<%= releaseHeader('2009-12-24', '0.1.2', '0.1.1') %> Fixed a bug with calling super() through more than one level of inheritance, with the re-addition of the extends keyword. Added experimental Narwhal support (as a Tusk package), contributed by Tom Robinson, including bin/cs as a CoffeeScript REPL and interpreter. New --no-wrap option to suppress the safety function wrapper.

<%= releaseHeader('2009-12-24', '0.1.1', '0.1.0') %> Added instanceof and typeof as operators.

<%= releaseHeader('2009-12-24', '0.1.0') %> Initial CoffeeScript release.

1.9.3~dfsg/documentation/vendor/0000755000000000000000000000000012531364553015443 5ustar rootroot1.9.3~dfsg/documentation/vendor/jquery-1.6.4.js0000644000000000000000000072111712531364553017775 0ustar rootroot/*! * jQuery JavaScript Library v1.6.4 * http://jquery.com/ * * Copyright 2011, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Includes Sizzle.js * http://sizzlejs.com/ * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * * Date: Mon Sep 12 18:54:48 2011 -0400 */ (function( window, undefined ) { // Use the correct document accordingly with window argument (sandbox) var document = window.document, navigator = window.navigator, location = window.location; var jQuery = (function() { // Define a local copy of jQuery var jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); }, // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ in case of overwrite _$ = window.$, // A central reference to the root jQuery(document) rootjQuery, // A simple way to check for HTML strings or ID strings // Prioritize #id over to avoid XSS via location.hash (#9521) quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, // Check if a string has a non-whitespace character in it rnotwhite = /\S/, // Used for trimming whitespace trimLeft = /^\s+/, trimRight = /\s+$/, // Check for digits rdigit = /\d/, // Match a standalone tag rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, // JSON RegExp rvalidchars = /^[\],:{}\s]*$/, rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, // Useragent RegExp rwebkit = /(webkit)[ \/]([\w.]+)/, ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, rmsie = /(msie) ([\w.]+)/, rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, // Matches dashed string for camelizing rdashAlpha = /-([a-z]|[0-9])/ig, rmsPrefix = /^-ms-/, // Used by jQuery.camelCase as callback to replace() fcamelCase = function( all, letter ) { return ( letter + "" ).toUpperCase(); }, // Keep a UserAgent string for use with jQuery.browser userAgent = navigator.userAgent, // For matching the engine and version of the browser browserMatch, // The deferred used on DOM ready readyList, // The ready event handler DOMContentLoaded, // Save a reference to some core methods toString = Object.prototype.toString, hasOwn = Object.prototype.hasOwnProperty, push = Array.prototype.push, slice = Array.prototype.slice, trim = String.prototype.trim, indexOf = Array.prototype.indexOf, // [[Class]] -> type pairs class2type = {}; jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function( selector, context, rootjQuery ) { var match, elem, ret, doc; // Handle $(""), $(null), or $(undefined) if ( !selector ) { return this; } // Handle $(DOMElement) if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; } // The body element only exists once, optimize finding it if ( selector === "body" && !context && document.body ) { this.context = document; this[0] = document.body; this.selector = selector; this.length = 1; return this; } // Handle HTML strings if ( typeof selector === "string" ) { // Are we dealing with HTML string or an ID? if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = quickExpr.exec( selector ); } // Verify a match, and that no context was specified for #id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) if ( match[1] ) { context = context instanceof jQuery ? context[0] : context; doc = (context ? context.ownerDocument || context : document); // If a single string is passed in and it's a single tag // just do a createElement and skip the rest ret = rsingleTag.exec( selector ); if ( ret ) { if ( jQuery.isPlainObject( context ) ) { selector = [ document.createElement( ret[1] ) ]; jQuery.fn.attr.call( selector, context, true ); } else { selector = [ doc.createElement( ret[1] ) ]; } } else { ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; } return jQuery.merge( this, selector ); // HANDLE: $("#id") } else { elem = document.getElementById( match[2] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id !== match[2] ) { return rootjQuery.find( selector ); } // Otherwise, we inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return (context || rootjQuery).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor( context ).find( selector ); } // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } if (selector.selector !== undefined) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray( selector, this ); }, // Start with an empty selector selector: "", // The current version of jQuery being used jquery: "1.6.4", // The default length of a jQuery object is 0 length: 0, // The number of elements contained in the matched element set size: function() { return this.length; }, toArray: function() { return slice.call( this, 0 ); }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function( num ) { return num == null ? // Return a 'clean' array this.toArray() : // Return just the object ( num < 0 ? this[ this.length + num ] : this[ num ] ); }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function( elems, name, selector ) { // Build a new jQuery matched element set var ret = this.constructor(); if ( jQuery.isArray( elems ) ) { push.apply( ret, elems ); } else { jQuery.merge( ret, elems ); } // Add the old object onto the stack (as a reference) ret.prevObject = this; ret.context = this.context; if ( name === "find" ) { ret.selector = this.selector + (this.selector ? " " : "") + selector; } else if ( name ) { ret.selector = this.selector + "." + name + "(" + selector + ")"; } // Return the newly-formed element set return ret; }, // Execute a callback for every element in the matched set. // (You can seed the arguments with an array of args, but this is // only used internally.) each: function( callback, args ) { return jQuery.each( this, callback, args ); }, ready: function( fn ) { // Attach the listeners jQuery.bindReady(); // Add the callback readyList.done( fn ); return this; }, eq: function( i ) { return i === -1 ? this.slice( i ) : this.slice( i, +i + 1 ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, slice: function() { return this.pushStack( slice.apply( this, arguments ), "slice", slice.call(arguments).join(",") ); }, map: function( callback ) { return this.pushStack( jQuery.map(this, function( elem, i ) { return callback.call( elem, i, elem ); })); }, end: function() { return this.prevObject || this.constructor(null); }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push: push, sort: [].sort, splice: [].splice }; // Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn; jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // extend jQuery itself if only one argument is passed if ( length === i ) { target = this; --i; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray(src) ? src : []; } else { clone = src && jQuery.isPlainObject(src) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; jQuery.extend({ noConflict: function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; }, // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // A counter to track how many items to wait for before // the ready event fires. See #6781 readyWait: 1, // Hold (or release) the ready event holdReady: function( hold ) { if ( hold ) { jQuery.readyWait++; } else { jQuery.ready( true ); } }, // Handle when the DOM is ready ready: function( wait ) { // Either a released hold or an DOMready/load event and not yet ready if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( !document.body ) { return setTimeout( jQuery.ready, 1 ); } // Remember that the DOM is ready jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be if ( wait !== true && --jQuery.readyWait > 0 ) { return; } // If there are functions bound, to execute readyList.resolveWith( document, [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.trigger ) { jQuery( document ).trigger( "ready" ).unbind( "ready" ); } } }, bindReady: function() { if ( readyList ) { return; } readyList = jQuery._Deferred(); // Catch cases where $(document).ready() is called after the // browser event has already occurred. if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready return setTimeout( jQuery.ready, 1 ); } // Mozilla, Opera and webkit nightlies currently support this event if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", jQuery.ready, false ); // If IE event model is used } else if ( document.attachEvent ) { // ensure firing before onload, // maybe late but safe also for iframes document.attachEvent( "onreadystatechange", DOMContentLoaded ); // A fallback to window.onload, that will always work window.attachEvent( "onload", jQuery.ready ); // If IE and not a frame // continually check to see if the document is ready var toplevel = false; try { toplevel = window.frameElement == null; } catch(e) {} if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); } } }, // See test/unit/core.js for details concerning isFunction. // Since version 1.3, DOM methods and functions like alert // aren't supported. They return false on IE (#2968). isFunction: function( obj ) { return jQuery.type(obj) === "function"; }, isArray: Array.isArray || function( obj ) { return jQuery.type(obj) === "array"; }, // A crude way of determining if an object is a window isWindow: function( obj ) { return obj && typeof obj === "object" && "setInterval" in obj; }, isNaN: function( obj ) { return obj == null || !rdigit.test( obj ) || isNaN( obj ); }, type: function( obj ) { return obj == null ? String( obj ) : class2type[ toString.call(obj) ] || "object"; }, isPlainObject: function( obj ) { // Must be an Object. // Because of IE, we also have to check the presence of the constructor property. // Make sure that DOM nodes and window objects don't pass through, as well if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; } try { // Not own constructor property must be Object if ( obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } } catch ( e ) { // IE8,9 Will throw exceptions on certain host objects #9897 return false; } // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. var key; for ( key in obj ) {} return key === undefined || hasOwn.call( obj, key ); }, isEmptyObject: function( obj ) { for ( var name in obj ) { return false; } return true; }, error: function( msg ) { throw msg; }, parseJSON: function( data ) { if ( typeof data !== "string" || !data ) { return null; } // Make sure leading/trailing whitespace is removed (IE can't handle it) data = jQuery.trim( data ); // Attempt to parse using the native JSON parser first if ( window.JSON && window.JSON.parse ) { return window.JSON.parse( data ); } // Make sure the incoming data is actual JSON // Logic borrowed from http://json.org/json2.js if ( rvalidchars.test( data.replace( rvalidescape, "@" ) .replace( rvalidtokens, "]" ) .replace( rvalidbraces, "")) ) { return (new Function( "return " + data ))(); } jQuery.error( "Invalid JSON: " + data ); }, // Cross-browser xml parsing parseXML: function( data ) { var xml, tmp; try { if ( window.DOMParser ) { // Standard tmp = new DOMParser(); xml = tmp.parseFromString( data , "text/xml" ); } else { // IE xml = new ActiveXObject( "Microsoft.XMLDOM" ); xml.async = "false"; xml.loadXML( data ); } } catch( e ) { xml = undefined; } if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { jQuery.error( "Invalid XML: " + data ); } return xml; }, noop: function() {}, // Evaluates a script in a global context // Workarounds based on findings by Jim Driscoll // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context globalEval: function( data ) { if ( data && rnotwhite.test( data ) ) { // We use execScript on Internet Explorer // We use an anonymous function so that context is window // rather than jQuery in Firefox ( window.execScript || function( data ) { window[ "eval" ].call( window, data ); } )( data ); } }, // Convert dashed to camelCase; used by the css and data modules // Microsoft forgot to hump their vendor prefix (#9572) camelCase: function( string ) { return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); }, nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); }, // args is for internal usage only each: function( object, callback, args ) { var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction( object ); if ( args ) { if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } } // A special, fast, case for the most common use of each } else { if ( isObj ) { for ( name in object ) { if ( callback.call( object[ name ], name, object[ name ] ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { break; } } } } return object; }, // Use native String.trim function wherever possible trim: trim ? function( text ) { return text == null ? "" : trim.call( text ); } : // Otherwise use our own trimming functionality function( text ) { return text == null ? "" : text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); }, // results is for internal usage only makeArray: function( array, results ) { var ret = results || []; if ( array != null ) { // The window, strings (and functions) also have 'length' // The extra typeof function check is to prevent crashes // in Safari 2 (See: #3039) // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 var type = jQuery.type( array ); if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { push.call( ret, array ); } else { jQuery.merge( ret, array ); } } return ret; }, inArray: function( elem, array ) { if ( !array ) { return -1; } if ( indexOf ) { return indexOf.call( array, elem ); } for ( var i = 0, length = array.length; i < length; i++ ) { if ( array[ i ] === elem ) { return i; } } return -1; }, merge: function( first, second ) { var i = first.length, j = 0; if ( typeof second.length === "number" ) { for ( var l = second.length; j < l; j++ ) { first[ i++ ] = second[ j ]; } } else { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; } } first.length = i; return first; }, grep: function( elems, callback, inv ) { var ret = [], retVal; inv = !!inv; // Go through the array, only saving the items // that pass the validator function for ( var i = 0, length = elems.length; i < length; i++ ) { retVal = !!callback( elems[ i ], i ); if ( inv !== retVal ) { ret.push( elems[ i ] ); } } return ret; }, // arg is for internal usage only map: function( elems, callback, arg ) { var value, key, ret = [], i = 0, length = elems.length, // jquery objects are treated as arrays isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; // Go through the array, translating each of the items to their if ( isArray ) { for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret[ ret.length ] = value; } } // Go through every key on the object, } else { for ( key in elems ) { value = callback( elems[ key ], key, arg ); if ( value != null ) { ret[ ret.length ] = value; } } } // Flatten any nested arrays return ret.concat.apply( [], ret ); }, // A global GUID counter for objects guid: 1, // Bind a function to a context, optionally partially applying any // arguments. proxy: function( fn, context ) { if ( typeof context === "string" ) { var tmp = fn[ context ]; context = fn; fn = tmp; } // Quick check to determine if target is callable, in the spec // this throws a TypeError, but we will just return undefined. if ( !jQuery.isFunction( fn ) ) { return undefined; } // Simulated bind var args = slice.call( arguments, 2 ), proxy = function() { return fn.apply( context, args.concat( slice.call( arguments ) ) ); }; // Set the guid of unique handler to the same of original handler, so it can be removed proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; return proxy; }, // Mutifunctional method to get and set values to a collection // The value/s can optionally be executed if it's a function access: function( elems, key, value, exec, fn, pass ) { var length = elems.length; // Setting many attributes if ( typeof key === "object" ) { for ( var k in key ) { jQuery.access( elems, k, key[k], exec, fn, value ); } return elems; } // Setting one attribute if ( value !== undefined ) { // Optionally, function values get executed if exec is true exec = !pass && exec && jQuery.isFunction(value); for ( var i = 0; i < length; i++ ) { fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); } return elems; } // Getting an attribute return length ? fn( elems[0], key ) : undefined; }, now: function() { return (new Date()).getTime(); }, // Use of jQuery.browser is frowned upon. // More details: http://docs.jquery.com/Utilities/jQuery.browser uaMatch: function( ua ) { ua = ua.toLowerCase(); var match = rwebkit.exec( ua ) || ropera.exec( ua ) || rmsie.exec( ua ) || ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || []; return { browser: match[1] || "", version: match[2] || "0" }; }, sub: function() { function jQuerySub( selector, context ) { return new jQuerySub.fn.init( selector, context ); } jQuery.extend( true, jQuerySub, this ); jQuerySub.superclass = this; jQuerySub.fn = jQuerySub.prototype = this(); jQuerySub.fn.constructor = jQuerySub; jQuerySub.sub = this.sub; jQuerySub.fn.init = function init( selector, context ) { if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { context = jQuerySub( context ); } return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); }; jQuerySub.fn.init.prototype = jQuerySub.fn; var rootjQuerySub = jQuerySub(document); return jQuerySub; }, browser: {} }); // Populate the class2type map jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); }); browserMatch = jQuery.uaMatch( userAgent ); if ( browserMatch.browser ) { jQuery.browser[ browserMatch.browser ] = true; jQuery.browser.version = browserMatch.version; } // Deprecated, use jQuery.browser.webkit instead if ( jQuery.browser.webkit ) { jQuery.browser.safari = true; } // IE doesn't match non-breaking spaces with \s if ( rnotwhite.test( "\xA0" ) ) { trimLeft = /^[\s\xA0]+/; trimRight = /[\s\xA0]+$/; } // All jQuery objects should point back to these rootjQuery = jQuery(document); // Cleanup functions for the document ready method if ( document.addEventListener ) { DOMContentLoaded = function() { document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); jQuery.ready(); }; } else if ( document.attachEvent ) { DOMContentLoaded = function() { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( document.readyState === "complete" ) { document.detachEvent( "onreadystatechange", DOMContentLoaded ); jQuery.ready(); } }; } // The DOM ready check for Internet Explorer function doScrollCheck() { if ( jQuery.isReady ) { return; } try { // If IE is used, use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ document.documentElement.doScroll("left"); } catch(e) { setTimeout( doScrollCheck, 1 ); return; } // and execute any waiting functions jQuery.ready(); } return jQuery; })(); var // Promise methods promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), // Static reference to slice sliceDeferred = [].slice; jQuery.extend({ // Create a simple deferred (one callbacks list) _Deferred: function() { var // callbacks list callbacks = [], // stored [ context , args ] fired, // to avoid firing when already doing so firing, // flag to know if the deferred has been cancelled cancelled, // the deferred itself deferred = { // done( f1, f2, ...) done: function() { if ( !cancelled ) { var args = arguments, i, length, elem, type, _fired; if ( fired ) { _fired = fired; fired = 0; } for ( i = 0, length = args.length; i < length; i++ ) { elem = args[ i ]; type = jQuery.type( elem ); if ( type === "array" ) { deferred.done.apply( deferred, elem ); } else if ( type === "function" ) { callbacks.push( elem ); } } if ( _fired ) { deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); } } return this; }, // resolve with given context and args resolveWith: function( context, args ) { if ( !cancelled && !fired && !firing ) { // make sure args are available (#8421) args = args || []; firing = 1; try { while( callbacks[ 0 ] ) { callbacks.shift().apply( context, args ); } } finally { fired = [ context, args ]; firing = 0; } } return this; }, // resolve with this as context and given arguments resolve: function() { deferred.resolveWith( this, arguments ); return this; }, // Has this deferred been resolved? isResolved: function() { return !!( firing || fired ); }, // Cancel cancel: function() { cancelled = 1; callbacks = []; return this; } }; return deferred; }, // Full fledged deferred (two callbacks list) Deferred: function( func ) { var deferred = jQuery._Deferred(), failDeferred = jQuery._Deferred(), promise; // Add errorDeferred methods, then and promise jQuery.extend( deferred, { then: function( doneCallbacks, failCallbacks ) { deferred.done( doneCallbacks ).fail( failCallbacks ); return this; }, always: function() { return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); }, fail: failDeferred.done, rejectWith: failDeferred.resolveWith, reject: failDeferred.resolve, isRejected: failDeferred.isResolved, pipe: function( fnDone, fnFail ) { return jQuery.Deferred(function( newDefer ) { jQuery.each( { done: [ fnDone, "resolve" ], fail: [ fnFail, "reject" ] }, function( handler, data ) { var fn = data[ 0 ], action = data[ 1 ], returned; if ( jQuery.isFunction( fn ) ) { deferred[ handler ](function() { returned = fn.apply( this, arguments ); if ( returned && jQuery.isFunction( returned.promise ) ) { returned.promise().then( newDefer.resolve, newDefer.reject ); } else { newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); } }); } else { deferred[ handler ]( newDefer[ action ] ); } }); }).promise(); }, // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object promise: function( obj ) { if ( obj == null ) { if ( promise ) { return promise; } promise = obj = {}; } var i = promiseMethods.length; while( i-- ) { obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; } return obj; } }); // Make sure only one callback list will be used deferred.done( failDeferred.cancel ).fail( deferred.cancel ); // Unexpose cancel delete deferred.cancel; // Call given func if any if ( func ) { func.call( deferred, deferred ); } return deferred; }, // Deferred helper when: function( firstParam ) { var args = arguments, i = 0, length = args.length, count = length, deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? firstParam : jQuery.Deferred(); function resolveFunc( i ) { return function( value ) { args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; if ( !( --count ) ) { // Strange bug in FF4: // Values changed onto the arguments object sometimes end up as undefined values // outside the $.when method. Cloning the object into a fresh array solves the issue deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); } }; } if ( length > 1 ) { for( ; i < length; i++ ) { if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { args[ i ].promise().then( resolveFunc(i), deferred.reject ); } else { --count; } } if ( !count ) { deferred.resolveWith( deferred, args ); } } else if ( deferred !== firstParam ) { deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); } return deferred.promise(); } }); jQuery.support = (function() { var div = document.createElement( "div" ), documentElement = document.documentElement, all, a, select, opt, input, marginDiv, support, fragment, body, testElementParent, testElement, testElementStyle, tds, events, eventName, i, isSupported; // Preliminary tests div.setAttribute("className", "t"); div.innerHTML = "
a"; all = div.getElementsByTagName( "*" ); a = div.getElementsByTagName( "a" )[ 0 ]; // Can't get basic test support if ( !all || !all.length || !a ) { return {}; } // First batch of supports tests select = document.createElement( "select" ); opt = select.appendChild( document.createElement("option") ); input = div.getElementsByTagName( "input" )[ 0 ]; support = { // IE strips leading whitespace when .innerHTML is used leadingWhitespace: ( div.firstChild.nodeType === 3 ), // Make sure that tbody elements aren't automatically inserted // IE will insert them into empty tables tbody: !div.getElementsByTagName( "tbody" ).length, // Make sure that link elements get serialized correctly by innerHTML // This requires a wrapper element in IE htmlSerialize: !!div.getElementsByTagName( "link" ).length, // Get the style information from getAttribute // (IE uses .cssText instead) style: /top/.test( a.getAttribute("style") ), // Make sure that URLs aren't manipulated // (IE normalizes it by default) hrefNormalized: ( a.getAttribute( "href" ) === "/a" ), // Make sure that element opacity exists // (IE uses filter instead) // Use a regex to work around a WebKit issue. See #5145 opacity: /^0.55$/.test( a.style.opacity ), // Verify style float existence // (IE uses styleFloat instead of cssFloat) cssFloat: !!a.style.cssFloat, // Make sure that if no value is specified for a checkbox // that it defaults to "on". // (WebKit defaults to "" instead) checkOn: ( input.value === "on" ), // Make sure that a selected-by-default option has a working selected property. // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) optSelected: opt.selected, // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) getSetAttribute: div.className !== "t", // Will be defined later submitBubbles: true, changeBubbles: true, focusinBubbles: false, deleteExpando: true, noCloneEvent: true, inlineBlockNeedsLayout: false, shrinkWrapBlocks: false, reliableMarginRight: true }; // Make sure checked status is properly cloned input.checked = true; support.noCloneChecked = input.cloneNode( true ).checked; // Make sure that the options inside disabled selects aren't marked as disabled // (WebKit marks them as disabled) select.disabled = true; support.optDisabled = !opt.disabled; // Test to see if it's possible to delete an expando from an element // Fails in Internet Explorer try { delete div.test; } catch( e ) { support.deleteExpando = false; } if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { div.attachEvent( "onclick", function() { // Cloning a node shouldn't copy over any // bound event handlers (IE does this) support.noCloneEvent = false; }); div.cloneNode( true ).fireEvent( "onclick" ); } // Check if a radio maintains it's value // after being appended to the DOM input = document.createElement("input"); input.value = "t"; input.setAttribute("type", "radio"); support.radioValue = input.value === "t"; input.setAttribute("checked", "checked"); div.appendChild( input ); fragment = document.createDocumentFragment(); fragment.appendChild( div.firstChild ); // WebKit doesn't clone checked state correctly in fragments support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; div.innerHTML = ""; // Figure out if the W3C box model works as expected div.style.width = div.style.paddingLeft = "1px"; body = document.getElementsByTagName( "body" )[ 0 ]; // We use our own, invisible, body unless the body is already present // in which case we use a div (#9239) testElement = document.createElement( body ? "div" : "body" ); testElementStyle = { visibility: "hidden", width: 0, height: 0, border: 0, margin: 0, background: "none" }; if ( body ) { jQuery.extend( testElementStyle, { position: "absolute", left: "-1000px", top: "-1000px" }); } for ( i in testElementStyle ) { testElement.style[ i ] = testElementStyle[ i ]; } testElement.appendChild( div ); testElementParent = body || documentElement; testElementParent.insertBefore( testElement, testElementParent.firstChild ); // Check if a disconnected checkbox will retain its checked // value of true after appended to the DOM (IE6/7) support.appendChecked = input.checked; support.boxModel = div.offsetWidth === 2; if ( "zoom" in div.style ) { // Check if natively block-level elements act like inline-block // elements when setting their display to 'inline' and giving // them layout // (IE < 8 does this) div.style.display = "inline"; div.style.zoom = 1; support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); // Check if elements with layout shrink-wrap their children // (IE 6 does this) div.style.display = ""; div.innerHTML = "
"; support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); } div.innerHTML = "
t
"; tds = div.getElementsByTagName( "td" ); // Check if table cells still have offsetWidth/Height when they are set // to display:none and there are still other visible table cells in a // table row; if so, offsetWidth/Height are not reliable for use when // determining if an element has been hidden directly using // display:none (it is still safe to use offsets if a parent element is // hidden; don safety goggles and see bug #4512 for more information). // (only IE 8 fails this test) isSupported = ( tds[ 0 ].offsetHeight === 0 ); tds[ 0 ].style.display = ""; tds[ 1 ].style.display = "none"; // Check if empty table cells still have offsetWidth/Height // (IE < 8 fail this test) support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); div.innerHTML = ""; // Check if div with explicit width and no margin-right incorrectly // gets computed margin-right based on width of container. For more // info see bug #3333 // Fails in WebKit before Feb 2011 nightlies // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right if ( document.defaultView && document.defaultView.getComputedStyle ) { marginDiv = document.createElement( "div" ); marginDiv.style.width = "0"; marginDiv.style.marginRight = "0"; div.appendChild( marginDiv ); support.reliableMarginRight = ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; } // Remove the body element we added testElement.innerHTML = ""; testElementParent.removeChild( testElement ); // Technique from Juriy Zaytsev // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ // We only care about the case where non-standard event systems // are used, namely in IE. Short-circuiting here helps us to // avoid an eval call (in setAttribute) which can cause CSP // to go haywire. See: https://developer.mozilla.org/en/Security/CSP if ( div.attachEvent ) { for( i in { submit: 1, change: 1, focusin: 1 } ) { eventName = "on" + i; isSupported = ( eventName in div ); if ( !isSupported ) { div.setAttribute( eventName, "return;" ); isSupported = ( typeof div[ eventName ] === "function" ); } support[ i + "Bubbles" ] = isSupported; } } // Null connected elements to avoid leaks in IE testElement = fragment = select = opt = body = marginDiv = div = input = null; return support; })(); // Keep track of boxModel jQuery.boxModel = jQuery.support.boxModel; var rbrace = /^(?:\{.*\}|\[.*\])$/, rmultiDash = /([A-Z])/g; jQuery.extend({ cache: {}, // Please use with caution uuid: 0, // Unique for each copy of jQuery on the page // Non-digits removed to match rinlinejQuery expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), // The following elements throw uncatchable exceptions if you // attempt to add expando properties to them. noData: { "embed": true, // Ban all objects except for Flash (which handle expandos) "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", "applet": true }, hasData: function( elem ) { elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; return !!elem && !isEmptyDataObject( elem ); }, data: function( elem, name, data, pvt /* Internal Use Only */ ) { if ( !jQuery.acceptData( elem ) ) { return; } var thisCache, ret, internalKey = jQuery.expando, getByName = typeof name === "string", // We have to handle DOM nodes and JS objects differently because IE6-7 // can't GC object references properly across the DOM-JS boundary isNode = elem.nodeType, // Only DOM nodes need the global jQuery cache; JS object data is // attached directly to the object so GC can occur automatically cache = isNode ? jQuery.cache : elem, // Only defining an ID for JS objects if its cache already exists allows // the code to shortcut on the same path as a DOM node with no cache id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; // Avoid doing any more work than we need to when trying to get data on an // object that has no data at all if ( (!id || (pvt && id && (cache[ id ] && !cache[ id ][ internalKey ]))) && getByName && data === undefined ) { return; } if ( !id ) { // Only DOM nodes need a new unique ID for each element since their data // ends up in the global cache if ( isNode ) { elem[ jQuery.expando ] = id = ++jQuery.uuid; } else { id = jQuery.expando; } } if ( !cache[ id ] ) { cache[ id ] = {}; // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery // metadata on plain JS objects when the object is serialized using // JSON.stringify if ( !isNode ) { cache[ id ].toJSON = jQuery.noop; } } // An object can be passed to jQuery.data instead of a key/value pair; this gets // shallow copied over onto the existing cache if ( typeof name === "object" || typeof name === "function" ) { if ( pvt ) { cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); } else { cache[ id ] = jQuery.extend(cache[ id ], name); } } thisCache = cache[ id ]; // Internal jQuery data is stored in a separate object inside the object's data // cache in order to avoid key collisions between internal data and user-defined // data if ( pvt ) { if ( !thisCache[ internalKey ] ) { thisCache[ internalKey ] = {}; } thisCache = thisCache[ internalKey ]; } if ( data !== undefined ) { thisCache[ jQuery.camelCase( name ) ] = data; } // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should // not attempt to inspect the internal events object using jQuery.data, as this // internal data object is undocumented and subject to change. if ( name === "events" && !thisCache[name] ) { return thisCache[ internalKey ] && thisCache[ internalKey ].events; } // Check for both converted-to-camel and non-converted data property names // If a data property was specified if ( getByName ) { // First Try to find as-is property data ret = thisCache[ name ]; // Test for null|undefined property data if ( ret == null ) { // Try to find the camelCased property ret = thisCache[ jQuery.camelCase( name ) ]; } } else { ret = thisCache; } return ret; }, removeData: function( elem, name, pvt /* Internal Use Only */ ) { if ( !jQuery.acceptData( elem ) ) { return; } var thisCache, // Reference to internal data cache key internalKey = jQuery.expando, isNode = elem.nodeType, // See jQuery.data for more information cache = isNode ? jQuery.cache : elem, // See jQuery.data for more information id = isNode ? elem[ jQuery.expando ] : jQuery.expando; // If there is already no cache entry for this object, there is no // purpose in continuing if ( !cache[ id ] ) { return; } if ( name ) { thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; if ( thisCache ) { // Support interoperable removal of hyphenated or camelcased keys if ( !thisCache[ name ] ) { name = jQuery.camelCase( name ); } delete thisCache[ name ]; // If there is no data left in the cache, we want to continue // and let the cache object itself get destroyed if ( !isEmptyDataObject(thisCache) ) { return; } } } // See jQuery.data for more information if ( pvt ) { delete cache[ id ][ internalKey ]; // Don't destroy the parent cache unless the internal data object // had been the only thing left in it if ( !isEmptyDataObject(cache[ id ]) ) { return; } } var internalCache = cache[ id ][ internalKey ]; // Browsers that fail expando deletion also refuse to delete expandos on // the window, but it will allow it on all other JS objects; other browsers // don't care // Ensure that `cache` is not a window object #10080 if ( jQuery.support.deleteExpando || !cache.setInterval ) { delete cache[ id ]; } else { cache[ id ] = null; } // We destroyed the entire user cache at once because it's faster than // iterating through each key, but we need to continue to persist internal // data if it existed if ( internalCache ) { cache[ id ] = {}; // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery // metadata on plain JS objects when the object is serialized using // JSON.stringify if ( !isNode ) { cache[ id ].toJSON = jQuery.noop; } cache[ id ][ internalKey ] = internalCache; // Otherwise, we need to eliminate the expando on the node to avoid // false lookups in the cache for entries that no longer exist } else if ( isNode ) { // IE does not allow us to delete expando properties from nodes, // nor does it have a removeAttribute function on Document nodes; // we must handle all of these cases if ( jQuery.support.deleteExpando ) { delete elem[ jQuery.expando ]; } else if ( elem.removeAttribute ) { elem.removeAttribute( jQuery.expando ); } else { elem[ jQuery.expando ] = null; } } }, // For internal use only. _data: function( elem, name, data ) { return jQuery.data( elem, name, data, true ); }, // A method for determining if a DOM node can handle the data expando acceptData: function( elem ) { if ( elem.nodeName ) { var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; if ( match ) { return !(match === true || elem.getAttribute("classid") !== match); } } return true; } }); jQuery.fn.extend({ data: function( key, value ) { var data = null; if ( typeof key === "undefined" ) { if ( this.length ) { data = jQuery.data( this[0] ); if ( this[0].nodeType === 1 ) { var attr = this[0].attributes, name; for ( var i = 0, l = attr.length; i < l; i++ ) { name = attr[i].name; if ( name.indexOf( "data-" ) === 0 ) { name = jQuery.camelCase( name.substring(5) ); dataAttr( this[0], name, data[ name ] ); } } } } return data; } else if ( typeof key === "object" ) { return this.each(function() { jQuery.data( this, key ); }); } var parts = key.split("."); parts[1] = parts[1] ? "." + parts[1] : ""; if ( value === undefined ) { data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); // Try to fetch any internally stored data first if ( data === undefined && this.length ) { data = jQuery.data( this[0], key ); data = dataAttr( this[0], key, data ); } return data === undefined && parts[1] ? this.data( parts[0] ) : data; } else { return this.each(function() { var $this = jQuery( this ), args = [ parts[0], value ]; $this.triggerHandler( "setData" + parts[1] + "!", args ); jQuery.data( this, key, value ); $this.triggerHandler( "changeData" + parts[1] + "!", args ); }); } }, removeData: function( key ) { return this.each(function() { jQuery.removeData( this, key ); }); } }); function dataAttr( elem, key, data ) { // If nothing was found internally, try to fetch any // data from the HTML5 data-* attribute if ( data === undefined && elem.nodeType === 1 ) { var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); data = elem.getAttribute( name ); if ( typeof data === "string" ) { try { data = data === "true" ? true : data === "false" ? false : data === "null" ? null : !jQuery.isNaN( data ) ? parseFloat( data ) : rbrace.test( data ) ? jQuery.parseJSON( data ) : data; } catch( e ) {} // Make sure we set the data so it isn't changed later jQuery.data( elem, key, data ); } else { data = undefined; } } return data; } // TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON // property to be considered empty objects; this property always exists in // order to make sure JSON.stringify does not expose internal metadata function isEmptyDataObject( obj ) { for ( var name in obj ) { if ( name !== "toJSON" ) { return false; } } return true; } function handleQueueMarkDefer( elem, type, src ) { var deferDataKey = type + "defer", queueDataKey = type + "queue", markDataKey = type + "mark", defer = jQuery.data( elem, deferDataKey, undefined, true ); if ( defer && ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { // Give room for hard-coded callbacks to fire first // and eventually mark/queue something else on the element setTimeout( function() { if ( !jQuery.data( elem, queueDataKey, undefined, true ) && !jQuery.data( elem, markDataKey, undefined, true ) ) { jQuery.removeData( elem, deferDataKey, true ); defer.resolve(); } }, 0 ); } } jQuery.extend({ _mark: function( elem, type ) { if ( elem ) { type = (type || "fx") + "mark"; jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); } }, _unmark: function( force, elem, type ) { if ( force !== true ) { type = elem; elem = force; force = false; } if ( elem ) { type = type || "fx"; var key = type + "mark", count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); if ( count ) { jQuery.data( elem, key, count, true ); } else { jQuery.removeData( elem, key, true ); handleQueueMarkDefer( elem, type, "mark" ); } } }, queue: function( elem, type, data ) { if ( elem ) { type = (type || "fx") + "queue"; var q = jQuery.data( elem, type, undefined, true ); // Speed up dequeue by getting out quickly if this is just a lookup if ( data ) { if ( !q || jQuery.isArray(data) ) { q = jQuery.data( elem, type, jQuery.makeArray(data), true ); } else { q.push( data ); } } return q || []; } }, dequeue: function( elem, type ) { type = type || "fx"; var queue = jQuery.queue( elem, type ), fn = queue.shift(), defer; // If the fx queue is dequeued, always remove the progress sentinel if ( fn === "inprogress" ) { fn = queue.shift(); } if ( fn ) { // Add a progress sentinel to prevent the fx queue from being // automatically dequeued if ( type === "fx" ) { queue.unshift("inprogress"); } fn.call(elem, function() { jQuery.dequeue(elem, type); }); } if ( !queue.length ) { jQuery.removeData( elem, type + "queue", true ); handleQueueMarkDefer( elem, type, "queue" ); } } }); jQuery.fn.extend({ queue: function( type, data ) { if ( typeof type !== "string" ) { data = type; type = "fx"; } if ( data === undefined ) { return jQuery.queue( this[0], type ); } return this.each(function() { var queue = jQuery.queue( this, type, data ); if ( type === "fx" && queue[0] !== "inprogress" ) { jQuery.dequeue( this, type ); } }); }, dequeue: function( type ) { return this.each(function() { jQuery.dequeue( this, type ); }); }, // Based off of the plugin by Clint Helfers, with permission. // http://blindsignals.com/index.php/2009/07/jquery-delay/ delay: function( time, type ) { time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; type = type || "fx"; return this.queue( type, function() { var elem = this; setTimeout(function() { jQuery.dequeue( elem, type ); }, time ); }); }, clearQueue: function( type ) { return this.queue( type || "fx", [] ); }, // Get a promise resolved when queues of a certain type // are emptied (fx is the type by default) promise: function( type, object ) { if ( typeof type !== "string" ) { object = type; type = undefined; } type = type || "fx"; var defer = jQuery.Deferred(), elements = this, i = elements.length, count = 1, deferDataKey = type + "defer", queueDataKey = type + "queue", markDataKey = type + "mark", tmp; function resolve() { if ( !( --count ) ) { defer.resolveWith( elements, [ elements ] ); } } while( i-- ) { if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { count++; tmp.done( resolve ); } } resolve(); return defer.promise(); } }); var rclass = /[\n\t\r]/g, rspace = /\s+/, rreturn = /\r/g, rtype = /^(?:button|input)$/i, rfocusable = /^(?:button|input|object|select|textarea)$/i, rclickable = /^a(?:rea)?$/i, rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, nodeHook, boolHook; jQuery.fn.extend({ attr: function( name, value ) { return jQuery.access( this, name, value, true, jQuery.attr ); }, removeAttr: function( name ) { return this.each(function() { jQuery.removeAttr( this, name ); }); }, prop: function( name, value ) { return jQuery.access( this, name, value, true, jQuery.prop ); }, removeProp: function( name ) { name = jQuery.propFix[ name ] || name; return this.each(function() { // try/catch handles cases where IE balks (such as removing a property on window) try { this[ name ] = undefined; delete this[ name ]; } catch( e ) {} }); }, addClass: function( value ) { var classNames, i, l, elem, setClass, c, cl; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).addClass( value.call(this, j, this.className) ); }); } if ( value && typeof value === "string" ) { classNames = value.split( rspace ); for ( i = 0, l = this.length; i < l; i++ ) { elem = this[ i ]; if ( elem.nodeType === 1 ) { if ( !elem.className && classNames.length === 1 ) { elem.className = value; } else { setClass = " " + elem.className + " "; for ( c = 0, cl = classNames.length; c < cl; c++ ) { if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { setClass += classNames[ c ] + " "; } } elem.className = jQuery.trim( setClass ); } } } } return this; }, removeClass: function( value ) { var classNames, i, l, elem, className, c, cl; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).removeClass( value.call(this, j, this.className) ); }); } if ( (value && typeof value === "string") || value === undefined ) { classNames = (value || "").split( rspace ); for ( i = 0, l = this.length; i < l; i++ ) { elem = this[ i ]; if ( elem.nodeType === 1 && elem.className ) { if ( value ) { className = (" " + elem.className + " ").replace( rclass, " " ); for ( c = 0, cl = classNames.length; c < cl; c++ ) { className = className.replace(" " + classNames[ c ] + " ", " "); } elem.className = jQuery.trim( className ); } else { elem.className = ""; } } } } return this; }, toggleClass: function( value, stateVal ) { var type = typeof value, isBool = typeof stateVal === "boolean"; if ( jQuery.isFunction( value ) ) { return this.each(function( i ) { jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); }); } return this.each(function() { if ( type === "string" ) { // toggle individual class names var className, i = 0, self = jQuery( this ), state = stateVal, classNames = value.split( rspace ); while ( (className = classNames[ i++ ]) ) { // check each className given, space seperated list state = isBool ? state : !self.hasClass( className ); self[ state ? "addClass" : "removeClass" ]( className ); } } else if ( type === "undefined" || type === "boolean" ) { if ( this.className ) { // store className if set jQuery._data( this, "__className__", this.className ); } // toggle whole className this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; } }); }, hasClass: function( selector ) { var className = " " + selector + " "; for ( var i = 0, l = this.length; i < l; i++ ) { if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { return true; } } return false; }, val: function( value ) { var hooks, ret, elem = this[0]; if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { return ret; } ret = elem.value; return typeof ret === "string" ? // handle most common string cases ret.replace(rreturn, "") : // handle cases where value is null/undef or number ret == null ? "" : ret; } return undefined; } var isFunction = jQuery.isFunction( value ); return this.each(function( i ) { var self = jQuery(this), val; if ( this.nodeType !== 1 ) { return; } if ( isFunction ) { val = value.call( this, i, self.val() ); } else { val = value; } // Treat null/undefined as ""; convert numbers to string if ( val == null ) { val = ""; } else if ( typeof val === "number" ) { val += ""; } else if ( jQuery.isArray( val ) ) { val = jQuery.map(val, function ( value ) { return value == null ? "" : value + ""; }); } hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; // If set returns undefined, fall back to normal setting if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { this.value = val; } }); } }); jQuery.extend({ valHooks: { option: { get: function( elem ) { // attributes.value is undefined in Blackberry 4.7 but // uses .value. See #6932 var val = elem.attributes.value; return !val || val.specified ? elem.value : elem.text; } }, select: { get: function( elem ) { var value, index = elem.selectedIndex, values = [], options = elem.options, one = elem.type === "select-one"; // Nothing was selected if ( index < 0 ) { return null; } // Loop through all the selected options for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { var option = options[ i ]; // Don't return options that are disabled or in a disabled optgroup if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { // Get the specific value for the option value = jQuery( option ).val(); // We don't need an array for one selects if ( one ) { return value; } // Multi-Selects return an array values.push( value ); } } // Fixes Bug #2551 -- select.val() broken in IE after form.reset() if ( one && !values.length && options.length ) { return jQuery( options[ index ] ).val(); } return values; }, set: function( elem, value ) { var values = jQuery.makeArray( value ); jQuery(elem).find("option").each(function() { this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; }); if ( !values.length ) { elem.selectedIndex = -1; } return values; } } }, attrFn: { val: true, css: true, html: true, text: true, data: true, width: true, height: true, offset: true }, attrFix: { // Always normalize to ensure hook usage tabindex: "tabIndex" }, attr: function( elem, name, value, pass ) { var nType = elem.nodeType; // don't get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return undefined; } if ( pass && name in jQuery.attrFn ) { return jQuery( elem )[ name ]( value ); } // Fallback to prop when attributes are not supported if ( !("getAttribute" in elem) ) { return jQuery.prop( elem, name, value ); } var ret, hooks, notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); // Normalize the name if needed if ( notxml ) { name = jQuery.attrFix[ name ] || name; hooks = jQuery.attrHooks[ name ]; if ( !hooks ) { // Use boolHook for boolean attributes if ( rboolean.test( name ) ) { hooks = boolHook; // Use nodeHook if available( IE6/7 ) } else if ( nodeHook ) { hooks = nodeHook; } } } if ( value !== undefined ) { if ( value === null ) { jQuery.removeAttr( elem, name ); return undefined; } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { elem.setAttribute( name, "" + value ); return value; } } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { return ret; } else { ret = elem.getAttribute( name ); // Non-existent attributes return null, we normalize to undefined return ret === null ? undefined : ret; } }, removeAttr: function( elem, name ) { var propName; if ( elem.nodeType === 1 ) { name = jQuery.attrFix[ name ] || name; jQuery.attr( elem, name, "" ); elem.removeAttribute( name ); // Set corresponding property to false for boolean attributes if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { elem[ propName ] = false; } } }, attrHooks: { type: { set: function( elem, value ) { // We can't allow the type property to be changed (since it causes problems in IE) if ( rtype.test( elem.nodeName ) && elem.parentNode ) { jQuery.error( "type property can't be changed" ); } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { // Setting the type on a radio button after the value resets the value in IE6-9 // Reset value to it's default in case type is set after value // This is for element creation var val = elem.value; elem.setAttribute( "type", value ); if ( val ) { elem.value = val; } return value; } } }, // Use the value property for back compat // Use the nodeHook for button elements in IE6/7 (#1954) value: { get: function( elem, name ) { if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { return nodeHook.get( elem, name ); } return name in elem ? elem.value : null; }, set: function( elem, value, name ) { if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { return nodeHook.set( elem, value, name ); } // Does not return so that setAttribute is also used elem.value = value; } } }, propFix: { tabindex: "tabIndex", readonly: "readOnly", "for": "htmlFor", "class": "className", maxlength: "maxLength", cellspacing: "cellSpacing", cellpadding: "cellPadding", rowspan: "rowSpan", colspan: "colSpan", usemap: "useMap", frameborder: "frameBorder", contenteditable: "contentEditable" }, prop: function( elem, name, value ) { var nType = elem.nodeType; // don't get/set properties on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return undefined; } var ret, hooks, notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); if ( notxml ) { // Fix name and attach hooks name = jQuery.propFix[ name ] || name; hooks = jQuery.propHooks[ name ]; } if ( value !== undefined ) { if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { return (elem[ name ] = value); } } else { if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { return ret; } else { return elem[ name ]; } } }, propHooks: { tabIndex: { get: function( elem ) { // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ var attributeNode = elem.getAttributeNode("tabindex"); return attributeNode && attributeNode.specified ? parseInt( attributeNode.value, 10 ) : rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 0 : undefined; } } } }); // Add the tabindex propHook to attrHooks for back-compat jQuery.attrHooks.tabIndex = jQuery.propHooks.tabIndex; // Hook for boolean attributes boolHook = { get: function( elem, name ) { // Align boolean attributes with corresponding properties // Fall back to attribute presence where some booleans are not supported var attrNode; return jQuery.prop( elem, name ) === true || ( attrNode = elem.getAttributeNode( name ) ) && attrNode.nodeValue !== false ? name.toLowerCase() : undefined; }, set: function( elem, value, name ) { var propName; if ( value === false ) { // Remove boolean attributes when set to false jQuery.removeAttr( elem, name ); } else { // value is true since we know at this point it's type boolean and not false // Set boolean attributes to the same name and set the DOM property propName = jQuery.propFix[ name ] || name; if ( propName in elem ) { // Only set the IDL specifically if it already exists on the element elem[ propName ] = true; } elem.setAttribute( name, name.toLowerCase() ); } return name; } }; // IE6/7 do not support getting/setting some attributes with get/setAttribute if ( !jQuery.support.getSetAttribute ) { // Use this for any attribute in IE6/7 // This fixes almost every IE6/7 issue nodeHook = jQuery.valHooks.button = { get: function( elem, name ) { var ret; ret = elem.getAttributeNode( name ); // Return undefined if nodeValue is empty string return ret && ret.nodeValue !== "" ? ret.nodeValue : undefined; }, set: function( elem, value, name ) { // Set the existing or create a new attribute node var ret = elem.getAttributeNode( name ); if ( !ret ) { ret = document.createAttribute( name ); elem.setAttributeNode( ret ); } return (ret.nodeValue = value + ""); } }; // Set width and height to auto instead of 0 on empty string( Bug #8150 ) // This is for removals jQuery.each([ "width", "height" ], function( i, name ) { jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { set: function( elem, value ) { if ( value === "" ) { elem.setAttribute( name, "auto" ); return value; } } }); }); } // Some attributes require a special call on IE if ( !jQuery.support.hrefNormalized ) { jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { get: function( elem ) { var ret = elem.getAttribute( name, 2 ); return ret === null ? undefined : ret; } }); }); } if ( !jQuery.support.style ) { jQuery.attrHooks.style = { get: function( elem ) { // Return undefined in the case of empty string // Normalize to lowercase since IE uppercases css property names return elem.style.cssText.toLowerCase() || undefined; }, set: function( elem, value ) { return (elem.style.cssText = "" + value); } }; } // Safari mis-reports the default selected property of an option // Accessing the parent's selectedIndex property fixes it if ( !jQuery.support.optSelected ) { jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { get: function( elem ) { var parent = elem.parentNode; if ( parent ) { parent.selectedIndex; // Make sure that it also works with optgroups, see #5701 if ( parent.parentNode ) { parent.parentNode.selectedIndex; } } return null; } }); } // Radios and checkboxes getter/setter if ( !jQuery.support.checkOn ) { jQuery.each([ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = { get: function( elem ) { // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified return elem.getAttribute("value") === null ? "on" : elem.value; } }; }); } jQuery.each([ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { set: function( elem, value ) { if ( jQuery.isArray( value ) ) { return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0); } } }); }); var rnamespaces = /\.(.*)$/, rformElems = /^(?:textarea|input|select)$/i, rperiod = /\./g, rspaces = / /g, rescape = /[^\w\s.|`]/g, fcleanup = function( nm ) { return nm.replace(rescape, "\\$&"); }; /* * A number of helper functions used for managing events. * Many of the ideas behind this code originated from * Dean Edwards' addEvent library. */ jQuery.event = { // Bind an event to an element // Original by Dean Edwards add: function( elem, types, handler, data ) { if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } if ( handler === false ) { handler = returnFalse; } else if ( !handler ) { // Fixes bug #7229. Fix recommended by jdalton return; } var handleObjIn, handleObj; if ( handler.handler ) { handleObjIn = handler; handler = handleObjIn.handler; } // Make sure that the function being executed has a unique ID if ( !handler.guid ) { handler.guid = jQuery.guid++; } // Init the element's event structure var elemData = jQuery._data( elem ); // If no elemData is found then we must be trying to bind to one of the // banned noData elements if ( !elemData ) { return; } var events = elemData.events, eventHandle = elemData.handle; if ( !events ) { elemData.events = events = {}; } if ( !eventHandle ) { elemData.handle = eventHandle = function( e ) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? jQuery.event.handle.apply( eventHandle.elem, arguments ) : undefined; }; } // Add elem as a property of the handle function // This is to prevent a memory leak with non-native events in IE. eventHandle.elem = elem; // Handle multiple events separated by a space // jQuery(...).bind("mouseover mouseout", fn); types = types.split(" "); var type, i = 0, namespaces; while ( (type = types[ i++ ]) ) { handleObj = handleObjIn ? jQuery.extend({}, handleObjIn) : { handler: handler, data: data }; // Namespaced event handlers if ( type.indexOf(".") > -1 ) { namespaces = type.split("."); type = namespaces.shift(); handleObj.namespace = namespaces.slice(0).sort().join("."); } else { namespaces = []; handleObj.namespace = ""; } handleObj.type = type; if ( !handleObj.guid ) { handleObj.guid = handler.guid; } // Get the current list of functions bound to this event var handlers = events[ type ], special = jQuery.event.special[ type ] || {}; // Init the event handler queue if ( !handlers ) { handlers = events[ type ] = []; // Check for a special event handler // Only use addEventListener/attachEvent if the special // events handler returns false if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { // Bind the global event handler to the element if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle, false ); } else if ( elem.attachEvent ) { elem.attachEvent( "on" + type, eventHandle ); } } } if ( special.add ) { special.add.call( elem, handleObj ); if ( !handleObj.handler.guid ) { handleObj.handler.guid = handler.guid; } } // Add the function to the element's handler list handlers.push( handleObj ); // Keep track of which events have been used, for event optimization jQuery.event.global[ type ] = true; } // Nullify elem to prevent memory leaks in IE elem = null; }, global: {}, // Detach an event or set of events from an element remove: function( elem, types, handler, pos ) { // don't do events on text and comment nodes if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } if ( handler === false ) { handler = returnFalse; } var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, elemData = jQuery.hasData( elem ) && jQuery._data( elem ), events = elemData && elemData.events; if ( !elemData || !events ) { return; } // types is actually an event object here if ( types && types.type ) { handler = types.handler; types = types.type; } // Unbind all events for the element if ( !types || typeof types === "string" && types.charAt(0) === "." ) { types = types || ""; for ( type in events ) { jQuery.event.remove( elem, type + types ); } return; } // Handle multiple events separated by a space // jQuery(...).unbind("mouseover mouseout", fn); types = types.split(" "); while ( (type = types[ i++ ]) ) { origType = type; handleObj = null; all = type.indexOf(".") < 0; namespaces = []; if ( !all ) { // Namespaced event handlers namespaces = type.split("."); type = namespaces.shift(); namespace = new RegExp("(^|\\.)" + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); } eventType = events[ type ]; if ( !eventType ) { continue; } if ( !handler ) { for ( j = 0; j < eventType.length; j++ ) { handleObj = eventType[ j ]; if ( all || namespace.test( handleObj.namespace ) ) { jQuery.event.remove( elem, origType, handleObj.handler, j ); eventType.splice( j--, 1 ); } } continue; } special = jQuery.event.special[ type ] || {}; for ( j = pos || 0; j < eventType.length; j++ ) { handleObj = eventType[ j ]; if ( handler.guid === handleObj.guid ) { // remove the given handler for the given type if ( all || namespace.test( handleObj.namespace ) ) { if ( pos == null ) { eventType.splice( j--, 1 ); } if ( special.remove ) { special.remove.call( elem, handleObj ); } } if ( pos != null ) { break; } } } // remove generic event handler if no more handlers exist if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { jQuery.removeEvent( elem, type, elemData.handle ); } ret = null; delete events[ type ]; } } // Remove the expando if it's no longer used if ( jQuery.isEmptyObject( events ) ) { var handle = elemData.handle; if ( handle ) { handle.elem = null; } delete elemData.events; delete elemData.handle; if ( jQuery.isEmptyObject( elemData ) ) { jQuery.removeData( elem, undefined, true ); } } }, // Events that are safe to short-circuit if no handlers are attached. // Native DOM events should not be added, they may have inline handlers. customEvent: { "getData": true, "setData": true, "changeData": true }, trigger: function( event, data, elem, onlyHandlers ) { // Event object or event type var type = event.type || event, namespaces = [], exclusive; if ( type.indexOf("!") >= 0 ) { // Exclusive events trigger only for the exact event (no namespaces) type = type.slice(0, -1); exclusive = true; } if ( type.indexOf(".") >= 0 ) { // Namespaced trigger; create a regexp to match event type in handle() namespaces = type.split("."); type = namespaces.shift(); namespaces.sort(); } if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { // No jQuery handlers for this event type, and it can't have inline handlers return; } // Caller can pass in an Event, Object, or just an event type string event = typeof event === "object" ? // jQuery.Event object event[ jQuery.expando ] ? event : // Object literal new jQuery.Event( type, event ) : // Just the event type (string) new jQuery.Event( type ); event.type = type; event.exclusive = exclusive; event.namespace = namespaces.join("."); event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); // triggerHandler() and global events don't bubble or run the default action if ( onlyHandlers || !elem ) { event.preventDefault(); event.stopPropagation(); } // Handle a global trigger if ( !elem ) { // TODO: Stop taunting the data cache; remove global events and always attach to document jQuery.each( jQuery.cache, function() { // internalKey variable is just used to make it easier to find // and potentially change this stuff later; currently it just // points to jQuery.expando var internalKey = jQuery.expando, internalCache = this[ internalKey ]; if ( internalCache && internalCache.events && internalCache.events[ type ] ) { jQuery.event.trigger( event, data, internalCache.handle.elem ); } }); return; } // Don't do events on text and comment nodes if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } // Clean up the event in case it is being reused event.result = undefined; event.target = elem; // Clone any incoming data and prepend the event, creating the handler arg list data = data != null ? jQuery.makeArray( data ) : []; data.unshift( event ); var cur = elem, // IE doesn't like method names with a colon (#3533, #8272) ontype = type.indexOf(":") < 0 ? "on" + type : ""; // Fire event on the current element, then bubble up the DOM tree do { var handle = jQuery._data( cur, "handle" ); event.currentTarget = cur; if ( handle ) { handle.apply( cur, data ); } // Trigger an inline bound script if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { event.result = false; event.preventDefault(); } // Bubble up to document, then to window cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; } while ( cur && !event.isPropagationStopped() ); // If nobody prevented the default action, do it now if ( !event.isDefaultPrevented() ) { var old, special = jQuery.event.special[ type ] || {}; if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { // Call a native DOM method on the target with the same name name as the event. // Can't use an .isFunction)() check here because IE6/7 fails that test. // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. try { if ( ontype && elem[ type ] ) { // Don't re-trigger an onFOO event when we call its FOO() method old = elem[ ontype ]; if ( old ) { elem[ ontype ] = null; } jQuery.event.triggered = type; elem[ type ](); } } catch ( ieError ) {} if ( old ) { elem[ ontype ] = old; } jQuery.event.triggered = undefined; } } return event.result; }, handle: function( event ) { event = jQuery.event.fix( event || window.event ); // Snapshot the handlers list since a called handler may add/remove events. var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), run_all = !event.exclusive && !event.namespace, args = Array.prototype.slice.call( arguments, 0 ); // Use the fix-ed Event rather than the (read-only) native event args[0] = event; event.currentTarget = this; for ( var j = 0, l = handlers.length; j < l; j++ ) { var handleObj = handlers[ j ]; // Triggered event must 1) be non-exclusive and have no namespace, or // 2) have namespace(s) a subset or equal to those in the bound event. if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { // Pass in a reference to the handler function itself // So that we can later remove it event.handler = handleObj.handler; event.data = handleObj.data; event.handleObj = handleObj; var ret = handleObj.handler.apply( this, args ); if ( ret !== undefined ) { event.result = ret; if ( ret === false ) { event.preventDefault(); event.stopPropagation(); } } if ( event.isImmediatePropagationStopped() ) { break; } } } return event.result; }, props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), fix: function( event ) { if ( event[ jQuery.expando ] ) { return event; } // store a copy of the original event object // and "clone" to set read-only properties var originalEvent = event; event = jQuery.Event( originalEvent ); for ( var i = this.props.length, prop; i; ) { prop = this.props[ --i ]; event[ prop ] = originalEvent[ prop ]; } // Fix target property, if necessary if ( !event.target ) { // Fixes #1925 where srcElement might not be defined either event.target = event.srcElement || document; } // check if target is a textnode (safari) if ( event.target.nodeType === 3 ) { event.target = event.target.parentNode; } // Add relatedTarget, if necessary if ( !event.relatedTarget && event.fromElement ) { event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; } // Calculate pageX/Y if missing and clientX/Y available if ( event.pageX == null && event.clientX != null ) { var eventDocument = event.target.ownerDocument || document, doc = eventDocument.documentElement, body = eventDocument.body; event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); } // Add which for key events if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { event.which = event.charCode != null ? event.charCode : event.keyCode; } // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) if ( !event.metaKey && event.ctrlKey ) { event.metaKey = event.ctrlKey; } // Add which for click: 1 === left; 2 === middle; 3 === right // Note: button is not normalized, so don't use it if ( !event.which && event.button !== undefined ) { event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); } return event; }, // Deprecated, use jQuery.guid instead guid: 1E8, // Deprecated, use jQuery.proxy instead proxy: jQuery.proxy, special: { ready: { // Make sure the ready event is setup setup: jQuery.bindReady, teardown: jQuery.noop }, live: { add: function( handleObj ) { jQuery.event.add( this, liveConvert( handleObj.origType, handleObj.selector ), jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); }, remove: function( handleObj ) { jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); } }, beforeunload: { setup: function( data, namespaces, eventHandle ) { // We only want to do this special case on windows if ( jQuery.isWindow( this ) ) { this.onbeforeunload = eventHandle; } }, teardown: function( namespaces, eventHandle ) { if ( this.onbeforeunload === eventHandle ) { this.onbeforeunload = null; } } } } }; jQuery.removeEvent = document.removeEventListener ? function( elem, type, handle ) { if ( elem.removeEventListener ) { elem.removeEventListener( type, handle, false ); } } : function( elem, type, handle ) { if ( elem.detachEvent ) { elem.detachEvent( "on" + type, handle ); } }; jQuery.Event = function( src, props ) { // Allow instantiation without the 'new' keyword if ( !this.preventDefault ) { return new jQuery.Event( src, props ); } // Event object if ( src && src.type ) { this.originalEvent = src; this.type = src.type; // Events bubbling up the document may have been marked as prevented // by a handler lower down the tree; reflect the correct value. this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; // Event type } else { this.type = src; } // Put explicitly provided properties onto the event object if ( props ) { jQuery.extend( this, props ); } // timeStamp is buggy for some events on Firefox(#3843) // So we won't rely on the native value this.timeStamp = jQuery.now(); // Mark it as fixed this[ jQuery.expando ] = true; }; function returnFalse() { return false; } function returnTrue() { return true; } // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html jQuery.Event.prototype = { preventDefault: function() { this.isDefaultPrevented = returnTrue; var e = this.originalEvent; if ( !e ) { return; } // if preventDefault exists run it on the original event if ( e.preventDefault ) { e.preventDefault(); // otherwise set the returnValue property of the original event to false (IE) } else { e.returnValue = false; } }, stopPropagation: function() { this.isPropagationStopped = returnTrue; var e = this.originalEvent; if ( !e ) { return; } // if stopPropagation exists run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); } // otherwise set the cancelBubble property of the original event to true (IE) e.cancelBubble = true; }, stopImmediatePropagation: function() { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); }, isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse }; // Checks if an event happened on an element within another element // Used in jQuery.event.special.mouseenter and mouseleave handlers var withinElement = function( event ) { // Check if mouse(over|out) are still within the same parent element var related = event.relatedTarget, inside = false, eventType = event.type; event.type = event.data; if ( related !== this ) { if ( related ) { inside = jQuery.contains( this, related ); } if ( !inside ) { jQuery.event.handle.apply( this, arguments ); event.type = eventType; } } }, // In case of event delegation, we only need to rename the event.type, // liveHandler will take care of the rest. delegate = function( event ) { event.type = event.data; jQuery.event.handle.apply( this, arguments ); }; // Create mouseenter and mouseleave events jQuery.each({ mouseenter: "mouseover", mouseleave: "mouseout" }, function( orig, fix ) { jQuery.event.special[ orig ] = { setup: function( data ) { jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); }, teardown: function( data ) { jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); } }; }); // submit delegation if ( !jQuery.support.submitBubbles ) { jQuery.event.special.submit = { setup: function( data, namespaces ) { if ( !jQuery.nodeName( this, "form" ) ) { jQuery.event.add(this, "click.specialSubmit", function( e ) { // Avoid triggering error on non-existent type attribute in IE VML (#7071) var elem = e.target, type = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.type : ""; if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { trigger( "submit", this, arguments ); } }); jQuery.event.add(this, "keypress.specialSubmit", function( e ) { var elem = e.target, type = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.type : ""; if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { trigger( "submit", this, arguments ); } }); } else { return false; } }, teardown: function( namespaces ) { jQuery.event.remove( this, ".specialSubmit" ); } }; } // change delegation, happens here so we have bind. if ( !jQuery.support.changeBubbles ) { var changeFilters, getVal = function( elem ) { var type = jQuery.nodeName( elem, "input" ) ? elem.type : "", val = elem.value; if ( type === "radio" || type === "checkbox" ) { val = elem.checked; } else if ( type === "select-multiple" ) { val = elem.selectedIndex > -1 ? jQuery.map( elem.options, function( elem ) { return elem.selected; }).join("-") : ""; } else if ( jQuery.nodeName( elem, "select" ) ) { val = elem.selectedIndex; } return val; }, testChange = function testChange( e ) { var elem = e.target, data, val; if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { return; } data = jQuery._data( elem, "_change_data" ); val = getVal(elem); // the current data will be also retrieved by beforeactivate if ( e.type !== "focusout" || elem.type !== "radio" ) { jQuery._data( elem, "_change_data", val ); } if ( data === undefined || val === data ) { return; } if ( data != null || val ) { e.type = "change"; e.liveFired = undefined; jQuery.event.trigger( e, arguments[1], elem ); } }; jQuery.event.special.change = { filters: { focusout: testChange, beforedeactivate: testChange, click: function( e ) { var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { testChange.call( this, e ); } }, // Change has to be called before submit // Keydown will be called before keypress, which is used in submit-event delegation keydown: function( e ) { var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || type === "select-multiple" ) { testChange.call( this, e ); } }, // Beforeactivate happens also before the previous element is blurred // with this event you can't trigger a change event, but you can store // information beforeactivate: function( e ) { var elem = e.target; jQuery._data( elem, "_change_data", getVal(elem) ); } }, setup: function( data, namespaces ) { if ( this.type === "file" ) { return false; } for ( var type in changeFilters ) { jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); } return rformElems.test( this.nodeName ); }, teardown: function( namespaces ) { jQuery.event.remove( this, ".specialChange" ); return rformElems.test( this.nodeName ); } }; changeFilters = jQuery.event.special.change.filters; // Handle when the input is .focus()'d changeFilters.focus = changeFilters.beforeactivate; } function trigger( type, elem, args ) { // Piggyback on a donor event to simulate a different one. // Fake originalEvent to avoid donor's stopPropagation, but if the // simulated event prevents default then we do the same on the donor. // Don't pass args or remember liveFired; they apply to the donor event. var event = jQuery.extend( {}, args[ 0 ] ); event.type = type; event.originalEvent = {}; event.liveFired = undefined; jQuery.event.handle.call( elem, event ); if ( event.isDefaultPrevented() ) { args[ 0 ].preventDefault(); } } // Create "bubbling" focus and blur events if ( !jQuery.support.focusinBubbles ) { jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { // Attach a single capturing handler while someone wants focusin/focusout var attaches = 0; jQuery.event.special[ fix ] = { setup: function() { if ( attaches++ === 0 ) { document.addEventListener( orig, handler, true ); } }, teardown: function() { if ( --attaches === 0 ) { document.removeEventListener( orig, handler, true ); } } }; function handler( donor ) { // Donor event is always a native one; fix it and switch its type. // Let focusin/out handler cancel the donor focus/blur event. var e = jQuery.event.fix( donor ); e.type = fix; e.originalEvent = {}; jQuery.event.trigger( e, null, e.target ); if ( e.isDefaultPrevented() ) { donor.preventDefault(); } } }); } jQuery.each(["bind", "one"], function( i, name ) { jQuery.fn[ name ] = function( type, data, fn ) { var handler; // Handle object literals if ( typeof type === "object" ) { for ( var key in type ) { this[ name ](key, data, type[key], fn); } return this; } if ( arguments.length === 2 || data === false ) { fn = data; data = undefined; } if ( name === "one" ) { handler = function( event ) { jQuery( this ).unbind( event, handler ); return fn.apply( this, arguments ); }; handler.guid = fn.guid || jQuery.guid++; } else { handler = fn; } if ( type === "unload" && name !== "one" ) { this.one( type, data, fn ); } else { for ( var i = 0, l = this.length; i < l; i++ ) { jQuery.event.add( this[i], type, handler, data ); } } return this; }; }); jQuery.fn.extend({ unbind: function( type, fn ) { // Handle object literals if ( typeof type === "object" && !type.preventDefault ) { for ( var key in type ) { this.unbind(key, type[key]); } } else { for ( var i = 0, l = this.length; i < l; i++ ) { jQuery.event.remove( this[i], type, fn ); } } return this; }, delegate: function( selector, types, data, fn ) { return this.live( types, data, fn, selector ); }, undelegate: function( selector, types, fn ) { if ( arguments.length === 0 ) { return this.unbind( "live" ); } else { return this.die( types, null, fn, selector ); } }, trigger: function( type, data ) { return this.each(function() { jQuery.event.trigger( type, data, this ); }); }, triggerHandler: function( type, data ) { if ( this[0] ) { return jQuery.event.trigger( type, data, this[0], true ); } }, toggle: function( fn ) { // Save reference to arguments for access in closure var args = arguments, guid = fn.guid || jQuery.guid++, i = 0, toggler = function( event ) { // Figure out which function to execute var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); // Make sure that clicks stop event.preventDefault(); // and execute the function return args[ lastToggle ].apply( this, arguments ) || false; }; // link all the functions, so any of them can unbind this click handler toggler.guid = guid; while ( i < args.length ) { args[ i++ ].guid = guid; } return this.click( toggler ); }, hover: function( fnOver, fnOut ) { return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); } }); var liveMap = { focus: "focusin", blur: "focusout", mouseenter: "mouseover", mouseleave: "mouseout" }; jQuery.each(["live", "die"], function( i, name ) { jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { var type, i = 0, match, namespaces, preType, selector = origSelector || this.selector, context = origSelector ? this : jQuery( this.context ); if ( typeof types === "object" && !types.preventDefault ) { for ( var key in types ) { context[ name ]( key, data, types[key], selector ); } return this; } if ( name === "die" && !types && origSelector && origSelector.charAt(0) === "." ) { context.unbind( origSelector ); return this; } if ( data === false || jQuery.isFunction( data ) ) { fn = data || returnFalse; data = undefined; } types = (types || "").split(" "); while ( (type = types[ i++ ]) != null ) { match = rnamespaces.exec( type ); namespaces = ""; if ( match ) { namespaces = match[0]; type = type.replace( rnamespaces, "" ); } if ( type === "hover" ) { types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); continue; } preType = type; if ( liveMap[ type ] ) { types.push( liveMap[ type ] + namespaces ); type = type + namespaces; } else { type = (liveMap[ type ] || type) + namespaces; } if ( name === "live" ) { // bind live handler for ( var j = 0, l = context.length; j < l; j++ ) { jQuery.event.add( context[j], "live." + liveConvert( type, selector ), { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); } } else { // unbind live handler context.unbind( "live." + liveConvert( type, selector ), fn ); } } return this; }; }); function liveHandler( event ) { var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, elems = [], selectors = [], events = jQuery._data( this, "events" ); // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { return; } if ( event.namespace ) { namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); } event.liveFired = this; var live = events.live.slice(0); for ( j = 0; j < live.length; j++ ) { handleObj = live[j]; if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { selectors.push( handleObj.selector ); } else { live.splice( j--, 1 ); } } match = jQuery( event.target ).closest( selectors, event.currentTarget ); for ( i = 0, l = match.length; i < l; i++ ) { close = match[i]; for ( j = 0; j < live.length; j++ ) { handleObj = live[j]; if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { elem = close.elem; related = null; // Those two events require additional checking if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { event.type = handleObj.preType; related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; // Make sure not to accidentally match a child element with the same selector if ( related && jQuery.contains( elem, related ) ) { related = elem; } } if ( !related || related !== elem ) { elems.push({ elem: elem, handleObj: handleObj, level: close.level }); } } } } for ( i = 0, l = elems.length; i < l; i++ ) { match = elems[i]; if ( maxLevel && match.level > maxLevel ) { break; } event.currentTarget = match.elem; event.data = match.handleObj.data; event.handleObj = match.handleObj; ret = match.handleObj.origHandler.apply( match.elem, arguments ); if ( ret === false || event.isPropagationStopped() ) { maxLevel = match.level; if ( ret === false ) { stop = false; } if ( event.isImmediatePropagationStopped() ) { break; } } } return stop; } function liveConvert( type, selector ) { return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); } jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { // Handle event binding jQuery.fn[ name ] = function( data, fn ) { if ( fn == null ) { fn = data; data = null; } return arguments.length > 0 ? this.bind( name, data, fn ) : this.trigger( name ); }; if ( jQuery.attrFn ) { jQuery.attrFn[ name ] = true; } }); /*! * Sizzle CSS Selector Engine * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ (function(){ var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, done = 0, toString = Object.prototype.toString, hasDuplicate = false, baseHasDuplicate = true, rBackslash = /\\/g, rNonWord = /\W/; // Here we check if the JavaScript engine is using some sort of // optimization where it does not always call our comparision // function. If that is the case, discard the hasDuplicate value. // Thus far that includes Google Chrome. [0, 0].sort(function() { baseHasDuplicate = false; return 0; }); var Sizzle = function( selector, context, results, seed ) { results = results || []; context = context || document; var origContext = context; if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } if ( !selector || typeof selector !== "string" ) { return results; } var m, set, checkSet, extra, ret, cur, pop, i, prune = true, contextXML = Sizzle.isXML( context ), parts = [], soFar = selector; // Reset the position of the chunker regexp (start from head) do { chunker.exec( "" ); m = chunker.exec( soFar ); if ( m ) { soFar = m[3]; parts.push( m[1] ); if ( m[2] ) { extra = m[3]; break; } } } while ( m ); if ( parts.length > 1 && origPOS.exec( selector ) ) { if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { set = posProcess( parts[0] + parts[1], context ); } else { set = Expr.relative[ parts[0] ] ? [ context ] : Sizzle( parts.shift(), context ); while ( parts.length ) { selector = parts.shift(); if ( Expr.relative[ selector ] ) { selector += parts.shift(); } set = posProcess( selector, set ); } } } else { // Take a shortcut and set the context if the root selector is an ID // (but not if it'll be faster if the inner selector is an ID) if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { ret = Sizzle.find( parts.shift(), context, contextXML ); context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; } if ( context ) { ret = seed ? { expr: parts.pop(), set: makeArray(seed) } : Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; if ( parts.length > 0 ) { checkSet = makeArray( set ); } else { prune = false; } while ( parts.length ) { cur = parts.pop(); pop = cur; if ( !Expr.relative[ cur ] ) { cur = ""; } else { pop = parts.pop(); } if ( pop == null ) { pop = context; } Expr.relative[ cur ]( checkSet, pop, contextXML ); } } else { checkSet = parts = []; } } if ( !checkSet ) { checkSet = set; } if ( !checkSet ) { Sizzle.error( cur || selector ); } if ( toString.call(checkSet) === "[object Array]" ) { if ( !prune ) { results.push.apply( results, checkSet ); } else if ( context && context.nodeType === 1 ) { for ( i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { results.push( set[i] ); } } } else { for ( i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && checkSet[i].nodeType === 1 ) { results.push( set[i] ); } } } } else { makeArray( checkSet, results ); } if ( extra ) { Sizzle( extra, origContext, results, seed ); Sizzle.uniqueSort( results ); } return results; }; Sizzle.uniqueSort = function( results ) { if ( sortOrder ) { hasDuplicate = baseHasDuplicate; results.sort( sortOrder ); if ( hasDuplicate ) { for ( var i = 1; i < results.length; i++ ) { if ( results[i] === results[ i - 1 ] ) { results.splice( i--, 1 ); } } } } return results; }; Sizzle.matches = function( expr, set ) { return Sizzle( expr, null, null, set ); }; Sizzle.matchesSelector = function( node, expr ) { return Sizzle( expr, null, null, [node] ).length > 0; }; Sizzle.find = function( expr, context, isXML ) { var set; if ( !expr ) { return []; } for ( var i = 0, l = Expr.order.length; i < l; i++ ) { var match, type = Expr.order[i]; if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { var left = match[1]; match.splice( 1, 1 ); if ( left.substr( left.length - 1 ) !== "\\" ) { match[1] = (match[1] || "").replace( rBackslash, "" ); set = Expr.find[ type ]( match, context, isXML ); if ( set != null ) { expr = expr.replace( Expr.match[ type ], "" ); break; } } } } if ( !set ) { set = typeof context.getElementsByTagName !== "undefined" ? context.getElementsByTagName( "*" ) : []; } return { set: set, expr: expr }; }; Sizzle.filter = function( expr, set, inplace, not ) { var match, anyFound, old = expr, result = [], curLoop = set, isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); while ( expr && set.length ) { for ( var type in Expr.filter ) { if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { var found, item, filter = Expr.filter[ type ], left = match[1]; anyFound = false; match.splice(1,1); if ( left.substr( left.length - 1 ) === "\\" ) { continue; } if ( curLoop === result ) { result = []; } if ( Expr.preFilter[ type ] ) { match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); if ( !match ) { anyFound = found = true; } else if ( match === true ) { continue; } } if ( match ) { for ( var i = 0; (item = curLoop[i]) != null; i++ ) { if ( item ) { found = filter( item, match, i, curLoop ); var pass = not ^ !!found; if ( inplace && found != null ) { if ( pass ) { anyFound = true; } else { curLoop[i] = false; } } else if ( pass ) { result.push( item ); anyFound = true; } } } } if ( found !== undefined ) { if ( !inplace ) { curLoop = result; } expr = expr.replace( Expr.match[ type ], "" ); if ( !anyFound ) { return []; } break; } } } // Improper expression if ( expr === old ) { if ( anyFound == null ) { Sizzle.error( expr ); } else { break; } } old = expr; } return curLoop; }; Sizzle.error = function( msg ) { throw "Syntax error, unrecognized expression: " + msg; }; var Expr = Sizzle.selectors = { order: [ "ID", "NAME", "TAG" ], match: { ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ }, leftMatch: {}, attrMap: { "class": "className", "for": "htmlFor" }, attrHandle: { href: function( elem ) { return elem.getAttribute( "href" ); }, type: function( elem ) { return elem.getAttribute( "type" ); } }, relative: { "+": function(checkSet, part){ var isPartStr = typeof part === "string", isTag = isPartStr && !rNonWord.test( part ), isPartStrNotTag = isPartStr && !isTag; if ( isTag ) { part = part.toLowerCase(); } for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { if ( (elem = checkSet[i]) ) { while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? elem || false : elem === part; } } if ( isPartStrNotTag ) { Sizzle.filter( part, checkSet, true ); } }, ">": function( checkSet, part ) { var elem, isPartStr = typeof part === "string", i = 0, l = checkSet.length; if ( isPartStr && !rNonWord.test( part ) ) { part = part.toLowerCase(); for ( ; i < l; i++ ) { elem = checkSet[i]; if ( elem ) { var parent = elem.parentNode; checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; } } } else { for ( ; i < l; i++ ) { elem = checkSet[i]; if ( elem ) { checkSet[i] = isPartStr ? elem.parentNode : elem.parentNode === part; } } if ( isPartStr ) { Sizzle.filter( part, checkSet, true ); } } }, "": function(checkSet, part, isXML){ var nodeCheck, doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !rNonWord.test( part ) ) { part = part.toLowerCase(); nodeCheck = part; checkFn = dirNodeCheck; } checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); }, "~": function( checkSet, part, isXML ) { var nodeCheck, doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !rNonWord.test( part ) ) { part = part.toLowerCase(); nodeCheck = part; checkFn = dirNodeCheck; } checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); } }, find: { ID: function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 return m && m.parentNode ? [m] : []; } }, NAME: function( match, context ) { if ( typeof context.getElementsByName !== "undefined" ) { var ret = [], results = context.getElementsByName( match[1] ); for ( var i = 0, l = results.length; i < l; i++ ) { if ( results[i].getAttribute("name") === match[1] ) { ret.push( results[i] ); } } return ret.length === 0 ? null : ret; } }, TAG: function( match, context ) { if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( match[1] ); } } }, preFilter: { CLASS: function( match, curLoop, inplace, result, not, isXML ) { match = " " + match[1].replace( rBackslash, "" ) + " "; if ( isXML ) { return match; } for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { if ( elem ) { if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { if ( !inplace ) { result.push( elem ); } } else if ( inplace ) { curLoop[i] = false; } } } return false; }, ID: function( match ) { return match[1].replace( rBackslash, "" ); }, TAG: function( match, curLoop ) { return match[1].replace( rBackslash, "" ).toLowerCase(); }, CHILD: function( match ) { if ( match[1] === "nth" ) { if ( !match[2] ) { Sizzle.error( match[0] ); } match[2] = match[2].replace(/^\+|\s*/g, ''); // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); // calculate the numbers (first)n+(last) including if they are negative match[2] = (test[1] + (test[2] || 1)) - 0; match[3] = test[3] - 0; } else if ( match[2] ) { Sizzle.error( match[0] ); } // TODO: Move to normal caching system match[0] = done++; return match; }, ATTR: function( match, curLoop, inplace, result, not, isXML ) { var name = match[1] = match[1].replace( rBackslash, "" ); if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } // Handle if an un-quoted value was used match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); if ( match[2] === "~=" ) { match[4] = " " + match[4] + " "; } return match; }, PSEUDO: function( match, curLoop, inplace, result, not ) { if ( match[1] === "not" ) { // If we're dealing with a complex expression, or a simple one if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { match[3] = Sizzle(match[3], null, null, curLoop); } else { var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); if ( !inplace ) { result.push.apply( result, ret ); } return false; } } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } return match; }, POS: function( match ) { match.unshift( true ); return match; } }, filters: { enabled: function( elem ) { return elem.disabled === false && elem.type !== "hidden"; }, disabled: function( elem ) { return elem.disabled === true; }, checked: function( elem ) { return elem.checked === true; }, selected: function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } return elem.selected === true; }, parent: function( elem ) { return !!elem.firstChild; }, empty: function( elem ) { return !elem.firstChild; }, has: function( elem, i, match ) { return !!Sizzle( match[3], elem ).length; }, header: function( elem ) { return (/h\d/i).test( elem.nodeName ); }, text: function( elem ) { var attr = elem.getAttribute( "type" ), type = elem.type; // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) // use getAttribute instead to test this case return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); }, radio: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; }, checkbox: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; }, file: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; }, password: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; }, submit: function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && "submit" === elem.type; }, image: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; }, reset: function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && "reset" === elem.type; }, button: function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && "button" === elem.type || name === "button"; }, input: function( elem ) { return (/input|select|textarea|button/i).test( elem.nodeName ); }, focus: function( elem ) { return elem === elem.ownerDocument.activeElement; } }, setFilters: { first: function( elem, i ) { return i === 0; }, last: function( elem, i, match, array ) { return i === array.length - 1; }, even: function( elem, i ) { return i % 2 === 0; }, odd: function( elem, i ) { return i % 2 === 1; }, lt: function( elem, i, match ) { return i < match[3] - 0; }, gt: function( elem, i, match ) { return i > match[3] - 0; }, nth: function( elem, i, match ) { return match[3] - 0 === i; }, eq: function( elem, i, match ) { return match[3] - 0 === i; } }, filter: { PSEUDO: function( elem, match, i, array ) { var name = match[1], filter = Expr.filters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } else if ( name === "contains" ) { return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; } else if ( name === "not" ) { var not = match[3]; for ( var j = 0, l = not.length; j < l; j++ ) { if ( not[j] === elem ) { return false; } } return true; } else { Sizzle.error( name ); } }, CHILD: function( elem, match ) { var type = match[1], node = elem; switch ( type ) { case "only": case "first": while ( (node = node.previousSibling) ) { if ( node.nodeType === 1 ) { return false; } } if ( type === "first" ) { return true; } node = elem; case "last": while ( (node = node.nextSibling) ) { if ( node.nodeType === 1 ) { return false; } } return true; case "nth": var first = match[2], last = match[3]; if ( first === 1 && last === 0 ) { return true; } var doneName = match[0], parent = elem.parentNode; if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { var count = 0; for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } } parent.sizcache = doneName; } var diff = elem.nodeIndex - last; if ( first === 0 ) { return diff === 0; } else { return ( diff % first === 0 && diff / first >= 0 ); } } }, ID: function( elem, match ) { return elem.nodeType === 1 && elem.getAttribute("id") === match; }, TAG: function( elem, match ) { return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; }, CLASS: function( elem, match ) { return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; }, ATTR: function( elem, match ) { var name = match[1], result = Expr.attrHandle[ name ] ? Expr.attrHandle[ name ]( elem ) : elem[ name ] != null ? elem[ name ] : elem.getAttribute( name ), value = result + "", type = match[2], check = match[4]; return result == null ? type === "!=" : type === "=" ? value === check : type === "*=" ? value.indexOf(check) >= 0 : type === "~=" ? (" " + value + " ").indexOf(check) >= 0 : !check ? value && result !== false : type === "!=" ? value !== check : type === "^=" ? value.indexOf(check) === 0 : type === "$=" ? value.substr(value.length - check.length) === check : type === "|=" ? value === check || value.substr(0, check.length + 1) === check + "-" : false; }, POS: function( elem, match, i, array ) { var name = match[2], filter = Expr.setFilters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } } } }; var origPOS = Expr.match.POS, fescape = function(all, num){ return "\\" + (num - 0 + 1); }; for ( var type in Expr.match ) { Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); } var makeArray = function( array, results ) { array = Array.prototype.slice.call( array, 0 ); if ( results ) { results.push.apply( results, array ); return results; } return array; }; // Perform a simple check to determine if the browser is capable of // converting a NodeList to an array using builtin methods. // Also verifies that the returned array holds DOM nodes // (which is not the case in the Blackberry browser) try { Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; // Provide a fallback method if it does not work } catch( e ) { makeArray = function( array, results ) { var i = 0, ret = results || []; if ( toString.call(array) === "[object Array]" ) { Array.prototype.push.apply( ret, array ); } else { if ( typeof array.length === "number" ) { for ( var l = array.length; i < l; i++ ) { ret.push( array[i] ); } } else { for ( ; array[i]; i++ ) { ret.push( array[i] ); } } } return ret; }; } var sortOrder, siblingCheck; if ( document.documentElement.compareDocumentPosition ) { sortOrder = function( a, b ) { if ( a === b ) { hasDuplicate = true; return 0; } if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { return a.compareDocumentPosition ? -1 : 1; } return a.compareDocumentPosition(b) & 4 ? -1 : 1; }; } else { sortOrder = function( a, b ) { // The nodes are identical, we can exit early if ( a === b ) { hasDuplicate = true; return 0; // Fallback to using sourceIndex (in IE) if it's available on both nodes } else if ( a.sourceIndex && b.sourceIndex ) { return a.sourceIndex - b.sourceIndex; } var al, bl, ap = [], bp = [], aup = a.parentNode, bup = b.parentNode, cur = aup; // If the nodes are siblings (or identical) we can do a quick check if ( aup === bup ) { return siblingCheck( a, b ); // If no parents were found then the nodes are disconnected } else if ( !aup ) { return -1; } else if ( !bup ) { return 1; } // Otherwise they're somewhere else in the tree so we need // to build up a full list of the parentNodes for comparison while ( cur ) { ap.unshift( cur ); cur = cur.parentNode; } cur = bup; while ( cur ) { bp.unshift( cur ); cur = cur.parentNode; } al = ap.length; bl = bp.length; // Start walking down the tree looking for a discrepancy for ( var i = 0; i < al && i < bl; i++ ) { if ( ap[i] !== bp[i] ) { return siblingCheck( ap[i], bp[i] ); } } // We ended someplace up the tree so do a sibling check return i === al ? siblingCheck( a, bp[i], -1 ) : siblingCheck( ap[i], b, 1 ); }; siblingCheck = function( a, b, ret ) { if ( a === b ) { return ret; } var cur = a.nextSibling; while ( cur ) { if ( cur === b ) { return -1; } cur = cur.nextSibling; } return 1; }; } // Utility function for retreiving the text value of an array of DOM nodes Sizzle.getText = function( elems ) { var ret = "", elem; for ( var i = 0; elems[i]; i++ ) { elem = elems[i]; // Get the text from text nodes and CDATA nodes if ( elem.nodeType === 3 || elem.nodeType === 4 ) { ret += elem.nodeValue; // Traverse everything else, except comment nodes } else if ( elem.nodeType !== 8 ) { ret += Sizzle.getText( elem.childNodes ); } } return ret; }; // Check to see if the browser returns elements by name when // querying by getElementById (and provide a workaround) (function(){ // We're going to inject a fake input element with a specified name var form = document.createElement("div"), id = "script" + (new Date()).getTime(), root = document.documentElement; form.innerHTML = ""; // Inject it into the root element, check its status, and remove it quickly root.insertBefore( form, root.firstChild ); // The workaround has to do additional checks after a getElementById // Which slows things down for other browsers (hence the branching) if ( document.getElementById( id ) ) { Expr.find.ID = function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; } }; Expr.filter.ID = function( elem, match ) { var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return elem.nodeType === 1 && node && node.nodeValue === match; }; } root.removeChild( form ); // release memory in IE root = form = null; })(); (function(){ // Check to see if the browser returns only elements // when doing getElementsByTagName("*") // Create a fake element var div = document.createElement("div"); div.appendChild( document.createComment("") ); // Make sure no comments are found if ( div.getElementsByTagName("*").length > 0 ) { Expr.find.TAG = function( match, context ) { var results = context.getElementsByTagName( match[1] ); // Filter out possible comments if ( match[1] === "*" ) { var tmp = []; for ( var i = 0; results[i]; i++ ) { if ( results[i].nodeType === 1 ) { tmp.push( results[i] ); } } results = tmp; } return results; }; } // Check to see if an attribute returns normalized href attributes div.innerHTML = ""; if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && div.firstChild.getAttribute("href") !== "#" ) { Expr.attrHandle.href = function( elem ) { return elem.getAttribute( "href", 2 ); }; } // release memory in IE div = null; })(); if ( document.querySelectorAll ) { (function(){ var oldSizzle = Sizzle, div = document.createElement("div"), id = "__sizzle__"; div.innerHTML = "

"; // Safari can't handle uppercase or unicode characters when // in quirks mode. if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } Sizzle = function( query, context, extra, seed ) { context = context || document; // Only use querySelectorAll on non-XML documents // (ID selectors don't work in non-HTML documents) if ( !seed && !Sizzle.isXML(context) ) { // See if we find a selector to speed up var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { // Speed-up: Sizzle("TAG") if ( match[1] ) { return makeArray( context.getElementsByTagName( query ), extra ); // Speed-up: Sizzle(".CLASS") } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { return makeArray( context.getElementsByClassName( match[2] ), extra ); } } if ( context.nodeType === 9 ) { // Speed-up: Sizzle("body") // The body element only exists once, optimize finding it if ( query === "body" && context.body ) { return makeArray( [ context.body ], extra ); // Speed-up: Sizzle("#ID") } else if ( match && match[3] ) { var elem = context.getElementById( match[3] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id === match[3] ) { return makeArray( [ elem ], extra ); } } else { return makeArray( [], extra ); } } try { return makeArray( context.querySelectorAll(query), extra ); } catch(qsaError) {} // qSA works strangely on Element-rooted queries // We can work around this by specifying an extra ID on the root // and working up from there (Thanks to Andrew Dupont for the technique) // IE 8 doesn't work on object elements } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { var oldContext = context, old = context.getAttribute( "id" ), nid = old || id, hasParent = context.parentNode, relativeHierarchySelector = /^\s*[+~]/.test( query ); if ( !old ) { context.setAttribute( "id", nid ); } else { nid = nid.replace( /'/g, "\\$&" ); } if ( relativeHierarchySelector && hasParent ) { context = context.parentNode; } try { if ( !relativeHierarchySelector || hasParent ) { return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); } } catch(pseudoError) { } finally { if ( !old ) { oldContext.removeAttribute( "id" ); } } } } return oldSizzle(query, context, extra, seed); }; for ( var prop in oldSizzle ) { Sizzle[ prop ] = oldSizzle[ prop ]; } // release memory in IE div = null; })(); } (function(){ var html = document.documentElement, matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; if ( matches ) { // Check to see if it's possible to do matchesSelector // on a disconnected node (IE 9 fails this) var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), pseudoWorks = false; try { // This should fail with an exception // Gecko does not error, returns false instead matches.call( document.documentElement, "[test!='']:sizzle" ); } catch( pseudoError ) { pseudoWorks = true; } Sizzle.matchesSelector = function( node, expr ) { // Make sure that attribute selectors are quoted expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); if ( !Sizzle.isXML( node ) ) { try { if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { var ret = matches.call( node, expr ); // IE 9's matchesSelector returns false on disconnected nodes if ( ret || !disconnectedMatch || // As well, disconnected nodes are said to be in a document // fragment in IE 9, so check for that node.document && node.document.nodeType !== 11 ) { return ret; } } } catch(e) {} } return Sizzle(expr, null, null, [node]).length > 0; }; } })(); (function(){ var div = document.createElement("div"); div.innerHTML = "
"; // Opera can't find a second classname (in 9.6) // Also, make sure that getElementsByClassName actually exists if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { return; } // Safari caches class attributes, doesn't catch changes (in 3.2) div.lastChild.className = "e"; if ( div.getElementsByClassName("e").length === 1 ) { return; } Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function( match, context, isXML ) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { return context.getElementsByClassName(match[1]); } }; // release memory in IE div = null; })(); function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var match = false; elem = elem[dir]; while ( elem ) { if ( elem.sizcache === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 && !isXML ){ elem.sizcache = doneName; elem.sizset = i; } if ( elem.nodeName.toLowerCase() === cur ) { match = elem; break; } elem = elem[dir]; } checkSet[i] = match; } } } function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var match = false; elem = elem[dir]; while ( elem ) { if ( elem.sizcache === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 ) { if ( !isXML ) { elem.sizcache = doneName; elem.sizset = i; } if ( typeof cur !== "string" ) { if ( elem === cur ) { match = true; break; } } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { match = elem; break; } } elem = elem[dir]; } checkSet[i] = match; } } } if ( document.documentElement.contains ) { Sizzle.contains = function( a, b ) { return a !== b && (a.contains ? a.contains(b) : true); }; } else if ( document.documentElement.compareDocumentPosition ) { Sizzle.contains = function( a, b ) { return !!(a.compareDocumentPosition(b) & 16); }; } else { Sizzle.contains = function() { return false; }; } Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; var posProcess = function( selector, context ) { var match, tmpSet = [], later = "", root = context.nodeType ? [context] : context; // Position selectors must be done after the filter // And so must :not(positional) so we move all PSEUDOs to the end while ( (match = Expr.match.PSEUDO.exec( selector )) ) { later += match[0]; selector = selector.replace( Expr.match.PSEUDO, "" ); } selector = Expr.relative[selector] ? selector + "*" : selector; for ( var i = 0, l = root.length; i < l; i++ ) { Sizzle( selector, root[i], tmpSet ); } return Sizzle.filter( later, tmpSet ); }; // EXPOSE jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; jQuery.expr[":"] = jQuery.expr.filters; jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; })(); var runtil = /Until$/, rparentsprev = /^(?:parents|prevUntil|prevAll)/, // Note: This RegExp should be improved, or likely pulled from Sizzle rmultiselector = /,/, isSimple = /^.[^:#\[\.,]*$/, slice = Array.prototype.slice, POS = jQuery.expr.match.POS, // methods guaranteed to produce a unique set when starting from a unique set guaranteedUnique = { children: true, contents: true, next: true, prev: true }; jQuery.fn.extend({ find: function( selector ) { var self = this, i, l; if ( typeof selector !== "string" ) { return jQuery( selector ).filter(function() { for ( i = 0, l = self.length; i < l; i++ ) { if ( jQuery.contains( self[ i ], this ) ) { return true; } } }); } var ret = this.pushStack( "", "find", selector ), length, n, r; for ( i = 0, l = this.length; i < l; i++ ) { length = ret.length; jQuery.find( selector, this[i], ret ); if ( i > 0 ) { // Make sure that the results are unique for ( n = length; n < ret.length; n++ ) { for ( r = 0; r < length; r++ ) { if ( ret[r] === ret[n] ) { ret.splice(n--, 1); break; } } } } } return ret; }, has: function( target ) { var targets = jQuery( target ); return this.filter(function() { for ( var i = 0, l = targets.length; i < l; i++ ) { if ( jQuery.contains( this, targets[i] ) ) { return true; } } }); }, not: function( selector ) { return this.pushStack( winnow(this, selector, false), "not", selector); }, filter: function( selector ) { return this.pushStack( winnow(this, selector, true), "filter", selector ); }, is: function( selector ) { return !!selector && ( typeof selector === "string" ? jQuery.filter( selector, this ).length > 0 : this.filter( selector ).length > 0 ); }, closest: function( selectors, context ) { var ret = [], i, l, cur = this[0]; // Array if ( jQuery.isArray( selectors ) ) { var match, selector, matches = {}, level = 1; if ( cur && selectors.length ) { for ( i = 0, l = selectors.length; i < l; i++ ) { selector = selectors[i]; if ( !matches[ selector ] ) { matches[ selector ] = POS.test( selector ) ? jQuery( selector, context || this.context ) : selector; } } while ( cur && cur.ownerDocument && cur !== context ) { for ( selector in matches ) { match = matches[ selector ]; if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { ret.push({ selector: selector, elem: cur, level: level }); } } cur = cur.parentNode; level++; } } return ret; } // String var pos = POS.test( selectors ) || typeof selectors !== "string" ? jQuery( selectors, context || this.context ) : 0; for ( i = 0, l = this.length; i < l; i++ ) { cur = this[i]; while ( cur ) { if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { ret.push( cur ); break; } else { cur = cur.parentNode; if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { break; } } } } ret = ret.length > 1 ? jQuery.unique( ret ) : ret; return this.pushStack( ret, "closest", selectors ); }, // Determine the position of an element within // the matched set of elements index: function( elem ) { // No argument, return index in parent if ( !elem ) { return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; } // index in selector if ( typeof elem === "string" ) { return jQuery.inArray( this[0], jQuery( elem ) ); } // Locate the position of the desired element return jQuery.inArray( // If it receives a jQuery object, the first element is used elem.jquery ? elem[0] : elem, this ); }, add: function( selector, context ) { var set = typeof selector === "string" ? jQuery( selector, context ) : jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), all = jQuery.merge( this.get(), set ); return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? all : jQuery.unique( all ) ); }, andSelf: function() { return this.add( this.prevObject ); } }); // A painfully simple check to see if an element is disconnected // from a document (should be improved, where feasible). function isDisconnected( node ) { return !node || !node.parentNode || node.parentNode.nodeType === 11; } jQuery.each({ parent: function( elem ) { var parent = elem.parentNode; return parent && parent.nodeType !== 11 ? parent : null; }, parents: function( elem ) { return jQuery.dir( elem, "parentNode" ); }, parentsUntil: function( elem, i, until ) { return jQuery.dir( elem, "parentNode", until ); }, next: function( elem ) { return jQuery.nth( elem, 2, "nextSibling" ); }, prev: function( elem ) { return jQuery.nth( elem, 2, "previousSibling" ); }, nextAll: function( elem ) { return jQuery.dir( elem, "nextSibling" ); }, prevAll: function( elem ) { return jQuery.dir( elem, "previousSibling" ); }, nextUntil: function( elem, i, until ) { return jQuery.dir( elem, "nextSibling", until ); }, prevUntil: function( elem, i, until ) { return jQuery.dir( elem, "previousSibling", until ); }, siblings: function( elem ) { return jQuery.sibling( elem.parentNode.firstChild, elem ); }, children: function( elem ) { return jQuery.sibling( elem.firstChild ); }, contents: function( elem ) { return jQuery.nodeName( elem, "iframe" ) ? elem.contentDocument || elem.contentWindow.document : jQuery.makeArray( elem.childNodes ); } }, function( name, fn ) { jQuery.fn[ name ] = function( until, selector ) { var ret = jQuery.map( this, fn, until ), // The variable 'args' was introduced in // https://github.com/jquery/jquery/commit/52a0238 // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. // http://code.google.com/p/v8/issues/detail?id=1050 args = slice.call(arguments); if ( !runtil.test( name ) ) { selector = until; } if ( selector && typeof selector === "string" ) { ret = jQuery.filter( selector, ret ); } ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { ret = ret.reverse(); } return this.pushStack( ret, name, args.join(",") ); }; }); jQuery.extend({ filter: function( expr, elems, not ) { if ( not ) { expr = ":not(" + expr + ")"; } return elems.length === 1 ? jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : jQuery.find.matches(expr, elems); }, dir: function( elem, dir, until ) { var matched = [], cur = elem[ dir ]; while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { if ( cur.nodeType === 1 ) { matched.push( cur ); } cur = cur[dir]; } return matched; }, nth: function( cur, result, dir, elem ) { result = result || 1; var num = 0; for ( ; cur; cur = cur[dir] ) { if ( cur.nodeType === 1 && ++num === result ) { break; } } return cur; }, sibling: function( n, elem ) { var r = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType === 1 && n !== elem ) { r.push( n ); } } return r; } }); // Implement the identical functionality for filter and not function winnow( elements, qualifier, keep ) { // Can't pass null or undefined to indexOf in Firefox 4 // Set to 0 to skip string check qualifier = qualifier || 0; if ( jQuery.isFunction( qualifier ) ) { return jQuery.grep(elements, function( elem, i ) { var retVal = !!qualifier.call( elem, i, elem ); return retVal === keep; }); } else if ( qualifier.nodeType ) { return jQuery.grep(elements, function( elem, i ) { return (elem === qualifier) === keep; }); } else if ( typeof qualifier === "string" ) { var filtered = jQuery.grep(elements, function( elem ) { return elem.nodeType === 1; }); if ( isSimple.test( qualifier ) ) { return jQuery.filter(qualifier, filtered, !keep); } else { qualifier = jQuery.filter( qualifier, filtered ); } } return jQuery.grep(elements, function( elem, i ) { return (jQuery.inArray( elem, qualifier ) >= 0) === keep; }); } var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, rleadingWhitespace = /^\s+/, rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, rtagName = /<([\w:]+)/, rtbody = /", "" ], legend: [ 1, "
", "
" ], thead: [ 1, "", "
" ], tr: [ 2, "", "
" ], td: [ 3, "", "
" ], col: [ 2, "", "
" ], area: [ 1, "", "" ], _default: [ 0, "", "" ] }; wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; // IE can't serialize and

CoffeeScript Test Suite



  



1.9.3~dfsg/test/option_parser.coffee0000644000000000000000000000247312531364553016317 0ustar  rootroot# Option Parser
# -------------

# TODO: refactor option parser tests

# Ensure that the OptionParser handles arguments correctly.
return unless require?
{OptionParser} = require './../lib/coffee-script/optparse'

opt = new OptionParser [
  ['-r', '--required [DIR]',  'desc required']
  ['-o', '--optional',        'desc optional']
  ['-l', '--list [FILES*]',   'desc list']
]

test "basic arguments", ->
  args = ['one', 'two', 'three', '-r', 'dir']
  result = opt.parse args
  arrayEq args, result.arguments
  eq undefined, result.required

test "boolean and parameterised options", ->
  result = opt.parse ['--optional', '-r', 'folder', 'one', 'two']
  ok result.optional
  eq 'folder', result.required
  arrayEq ['one', 'two'], result.arguments

test "list options", ->
  result = opt.parse ['-l', 'one.txt', '-l', 'two.txt', 'three']
  arrayEq ['one.txt', 'two.txt'], result.list
  arrayEq ['three'], result.arguments

test "-- and interesting combinations", ->
  result = opt.parse ['-o','-r','a','-r','b','-o','--','-a','b','--c','d']
  arrayEq ['-a', 'b', '--c', 'd'], result.arguments
  ok result.optional
  eq 'b', result.required

  args = ['--','-o','a','-r','c','-o','--','-a','arg0','-b','arg1']
  result = opt.parse args
  eq undefined, result.optional
  eq undefined, result.required
  arrayEq args[1..], result.arguments
1.9.3~dfsg/test/compilation.coffee0000644000000000000000000000655412531364553015755 0ustar  rootroot# Compilation
# -----------

# helper to assert that a string should fail compilation
cantCompile = (code) ->
  throws -> CoffeeScript.compile code


test "ensure that carriage returns don't break compilation on Windows", ->
  doesNotThrow -> CoffeeScript.compile 'one\r\ntwo', bare: on

test "#3089 - don't mutate passed in options to compile", ->
  opts = {}
  CoffeeScript.compile '1 + 1', opts
  ok !opts.scope 

test "--bare", ->
  eq -1, CoffeeScript.compile('x = y', bare: on).indexOf 'function'
  ok 'passed' is CoffeeScript.eval '"passed"', bare: on, filename: 'test'

test "header (#1778)", ->
  header = "// Generated by CoffeeScript #{CoffeeScript.VERSION}\n"
  eq 0, CoffeeScript.compile('x = y', header: on).indexOf header

test "header is disabled by default", ->
  header = "// Generated by CoffeeScript #{CoffeeScript.VERSION}\n"
  eq -1, CoffeeScript.compile('x = y').indexOf header

test "multiple generated references", ->
  a = {b: []}
  a.b[true] = -> this == a.b
  c = 0
  d = []
  ok a.b[0<++c<2] d...

test "splat on a line by itself is invalid", ->
  cantCompile "x 'a'\n...\n"

test "Issue 750", ->

  cantCompile 'f(->'

  cantCompile 'a = (break)'

  cantCompile 'a = (return 5 for item in list)'

  cantCompile 'a = (return 5 while condition)'

  cantCompile 'a = for x in y\n  return 5'

test "Issue #986: Unicode identifiers", ->
  λ = 5
  eq λ, 5

test "#2516: Unicode spaces should not be part of identifiers", ->
  a = (x) -> x * 2
  b = 3
  eq 6, a b # U+00A0 NO-BREAK SPACE
  eq 6, a b # U+1680 OGHAM SPACE MARK
  eq 6, a b # U+2000 EN QUAD
  eq 6, a b # U+2001 EM QUAD
  eq 6, a b # U+2002 EN SPACE
  eq 6, a b # U+2003 EM SPACE
  eq 6, a b # U+2004 THREE-PER-EM SPACE
  eq 6, a b # U+2005 FOUR-PER-EM SPACE
  eq 6, a b # U+2006 SIX-PER-EM SPACE
  eq 6, a b # U+2007 FIGURE SPACE
  eq 6, a b # U+2008 PUNCTUATION SPACE
  eq 6, a b # U+2009 THIN SPACE
  eq 6, a b # U+200A HAIR SPACE
  eq 6, a b # U+202F NARROW NO-BREAK SPACE
  eq 6, a b # U+205F MEDIUM MATHEMATICAL SPACE
  eq 6, a b # U+3000 IDEOGRAPHIC SPACE

  # #3560: Non-breaking space (U+00A0) (before `'c'`)
  eq 5, {c: 5}[ 'c' ]

  # A line where every space in non-breaking
  eq 1 + 1, 2  

test "don't accidentally stringify keywords", ->
  ok (-> this == 'this')() is false

test "#1026: no if/else/else allowed", ->
  cantCompile '''
    if a
      b
    else
      c
    else
      d
  '''

test "#1050: no closing asterisk comments from within block comments", ->
  cantCompile "### */ ###"

test "#1273: escaping quotes at the end of heredocs", ->
  cantCompile '"""\\"""' # """\"""
  cantCompile '"""\\\\\\"""' # """\\\"""

test "#1106: __proto__ compilation", ->
  object = eq
  @["__proto__"] = true
  ok __proto__

test "reference named hasOwnProperty", ->
  CoffeeScript.compile 'hasOwnProperty = 0; a = 1'

test "#1055: invalid keys in real (but not work-product) objects", ->
  cantCompile "@key: value"

test "#1066: interpolated strings are not implicit functions", ->
  cantCompile '"int#{er}polated" arg'

test "#2846: while with empty body", ->
  CoffeeScript.compile 'while 1 then', {sourceMap: true}

test "#2944: implicit call with a regex argument", ->
  CoffeeScript.compile 'o[key] /regex/'

test "#3001: `own` shouldn't be allowed in a `for`-`in` loop", ->
  cantCompile "a for own b in c"

test "#2994: single-line `if` requires `then`", ->
  cantCompile "if b else x"
1.9.3~dfsg/test/arrays.coffee0000644000000000000000000000367212531364553014736 0ustar  rootroot# Array Literals
# --------------

# * Array Literals
# * Splats in Array Literals

# TODO: add indexing and method invocation tests: [1][0] is 1, [].toString()

test "trailing commas", ->
  trailingComma = [1, 2, 3,]
  ok (trailingComma[0] is 1) and (trailingComma[2] is 3) and (trailingComma.length is 3)

  trailingComma = [
    1, 2, 3,
    4, 5, 6
    7, 8, 9,
  ]
  (sum = (sum or 0) + n) for n in trailingComma

  a = [((x) -> x), ((x) -> x * x)]
  ok a.length is 2

test "incorrect indentation without commas", ->
  result = [['a']
   {b: 'c'}]
  ok result[0][0] is 'a'
  ok result[1]['b'] is 'c'


# Splats in Array Literals

test "array splat expansions with assignments", ->
  nums = [1, 2, 3]
  list = [a = 0, nums..., b = 4]
  eq 0, a
  eq 4, b
  arrayEq [0,1,2,3,4], list


test "mixed shorthand objects in array lists", ->

  arr = [
    a:1
    'b'
    c:1
  ]
  ok arr.length is 3
  ok arr[2].c is 1

  arr = [b: 1, a: 2, 100]
  eq arr[1], 100

  arr = [a:0, b:1, (1 + 1)]
  eq arr[1], 2

  arr = [a:1, 'a', b:1, 'b']
  eq arr.length, 4
  eq arr[2].b, 1
  eq arr[3], 'b'


test "array splats with nested arrays", ->
  nonce = {}
  a = [nonce]
  list = [1, 2, a...]
  eq list[0], 1
  eq list[2], nonce

  a = [[nonce]]
  list = [1, 2, a...]
  arrayEq list, [1, 2, [nonce]]

test "#1274: `[] = a()` compiles to `false` instead of `a()`", ->
  a = false
  fn = -> a = true
  [] = fn()
  ok a

test "#3194: string interpolation in array", ->
  arr = [ "a"
          key: 'value'
        ]
  eq 2, arr.length
  eq 'a', arr[0]
  eq 'value', arr[1].key

  b = 'b'
  arr = [ "a#{b}"
          key: 'value'
        ]
  eq 2, arr.length
  eq 'ab', arr[0]
  eq 'value', arr[1].key

test "regex interpolation in array", ->
  arr = [ /a/
          key: 'value'
        ]
  eq 2, arr.length
  eq 'a', arr[0].source
  eq 'value', arr[1].key

  b = 'b'
  arr = [ ///a#{b}///
          key: 'value'
        ]
  eq 2, arr.length
  eq 'ab', arr[0].source
  eq 'value', arr[1].key
1.9.3~dfsg/test/assignment.coffee0000644000000000000000000002723612531364553015607 0ustar  rootroot# Assignment
# ----------

# * Assignment
# * Compound Assignment
# * Destructuring Assignment
# * Context Property (@) Assignment
# * Existential Assignment (?=)
# * Assignment to variables similar to generated variables

test "context property assignment (using @)", ->
  nonce = {}
  addMethod = ->
    @method = -> nonce
    this
  eq nonce, addMethod.call({}).method()

test "unassignable values", ->
  nonce = {}
  for nonref in ['', '""', '0', 'f()'].concat CoffeeScript.RESERVED
    eq nonce, (try CoffeeScript.compile "#{nonref} = v" catch e then nonce)

# Compound Assignment

test "boolean operators", ->
  nonce = {}

  a  = 0
  a or= nonce
  eq nonce, a

  b  = 1
  b or= nonce
  eq 1, b

  c = 0
  c and= nonce
  eq 0, c

  d = 1
  d and= nonce
  eq nonce, d

  # ensure that RHS is treated as a group
  e = f = false
  e and= f or true
  eq false, e

test "compound assignment as a sub expression", ->
  [a, b, c] = [1, 2, 3]
  eq 6, (a + b += c)
  eq 1, a
  eq 5, b
  eq 3, c

# *note: this test could still use refactoring*
test "compound assignment should be careful about caching variables", ->
  count = 0
  list = []

  list[++count] or= 1
  eq 1, list[1]
  eq 1, count

  list[++count] ?= 2
  eq 2, list[2]
  eq 2, count

  list[count++] and= 6
  eq 6, list[2]
  eq 3, count

  base = ->
    ++count
    base

  base().four or= 4
  eq 4, base.four
  eq 4, count

  base().five ?= 5
  eq 5, base.five
  eq 5, count

  eq 5, base().five ?= 6
  eq 6, count

test "compound assignment with implicit objects", ->
  obj = undefined
  obj ?=
    one: 1

  eq 1, obj.one

  obj and=
    two: 2

  eq undefined, obj.one
  eq         2, obj.two

test "compound assignment (math operators)", ->
  num = 10
  num -= 5
  eq 5, num

  num *= 10
  eq 50, num

  num /= 10
  eq 5, num

  num %= 3
  eq 2, num

test "more compound assignment", ->
  a = {}
  val = undefined
  val ||= a
  val ||= true
  eq a, val

  b = {}
  val &&= true
  eq val, true
  val &&= b
  eq b, val

  c = {}
  val = null
  val ?= c
  val ?= true
  eq c, val


# Destructuring Assignment

test "empty destructuring assignment", ->
  {} = [] = undefined

test "chained destructuring assignments", ->
  [a] = {0: b} = {'0': c} = [nonce={}]
  eq nonce, a
  eq nonce, b
  eq nonce, c

test "variable swapping to verify caching of RHS values when appropriate", ->
  a = nonceA = {}
  b = nonceB = {}
  c = nonceC = {}
  [a, b, c] = [b, c, a]
  eq nonceB, a
  eq nonceC, b
  eq nonceA, c
  [a, b, c] = [b, c, a]
  eq nonceC, a
  eq nonceA, b
  eq nonceB, c
  fn = ->
    [a, b, c] = [b, c, a]
  arrayEq [nonceA,nonceB,nonceC], fn()
  eq nonceA, a
  eq nonceB, b
  eq nonceC, c

test "#713: destructuring assignment should return right-hand-side value", ->
  nonces = [nonceA={},nonceB={}]
  eq nonces, [a, b] = [c, d] = nonces
  eq nonceA, a
  eq nonceA, c
  eq nonceB, b
  eq nonceB, d

test "destructuring assignment with splats", ->
  a = {}; b = {}; c = {}; d = {}; e = {}
  [x,y...,z] = [a,b,c,d,e]
  eq a, x
  arrayEq [b,c,d], y
  eq e, z

test "deep destructuring assignment with splats", ->
  a={}; b={}; c={}; d={}; e={}; f={}; g={}; h={}; i={}
  [u, [v, w..., x], y..., z] = [a, [b, c, d, e], f, g, h, i]
  eq a, u
  eq b, v
  arrayEq [c,d], w
  eq e, x
  arrayEq [f,g,h], y
  eq i, z

test "destructuring assignment with objects", ->
  a={}; b={}; c={}
  obj = {a,b,c}
  {a:x, b:y, c:z} = obj
  eq a, x
  eq b, y
  eq c, z

test "deep destructuring assignment with objects", ->
  a={}; b={}; c={}; d={}
  obj = {
    a
    b: {
      'c': {
        d: [
          b
          {e: c, f: d}
        ]
      }
    }
  }
  {a: w, 'b': {c: d: [x, {'f': z, e: y}]}} = obj
  eq a, w
  eq b, x
  eq c, y
  eq d, z

test "destructuring assignment with objects and splats", ->
  a={}; b={}; c={}; d={}
  obj = a: b: [a, b, c, d]
  {a: b: [y, z...]} = obj
  eq a, y
  arrayEq [b,c,d], z

test "destructuring assignment against an expression", ->
  a={}; b={}
  [y, z] = if true then [a, b] else [b, a]
  eq a, y
  eq b, z

test "bracket insertion when necessary", ->
  [a] = [0] ? [1]
  eq a, 0

# for implicit destructuring assignment in comprehensions, see the comprehension tests

test "destructuring assignment with context (@) properties", ->
  a={}; b={}; c={}; d={}; e={}
  obj =
    fn: () ->
      local = [a, {b, c}, d, e]
      [@a, {b: @b, c: @c}, @d, @e] = local
  eq undefined, obj[key] for key in ['a','b','c','d','e']
  obj.fn()
  eq a, obj.a
  eq b, obj.b
  eq c, obj.c
  eq d, obj.d
  eq e, obj.e

test "#1024: destructure empty assignments to produce javascript-like results", ->
  eq 2 * [] = 3 + 5, 16

test "#1005: invalid identifiers allowed on LHS of destructuring assignment", ->
  disallowed = ['eval', 'arguments'].concat CoffeeScript.RESERVED
  throws (-> CoffeeScript.compile "[#{disallowed.join ', '}] = x"), null, 'all disallowed'
  throws (-> CoffeeScript.compile "[#{disallowed.join '..., '}...] = x"), null, 'all disallowed as splats'
  t = tSplat = null
  for v in disallowed when v isnt 'class' # `class` by itself is an expression
    throws (-> CoffeeScript.compile t), null, t = "[#{v}] = x"
    throws (-> CoffeeScript.compile tSplat), null, tSplat = "[#{v}...] = x"
  doesNotThrow ->
    for v in disallowed
      CoffeeScript.compile "[a.#{v}] = x"
      CoffeeScript.compile "[a.#{v}...] = x"
      CoffeeScript.compile "[@#{v}] = x"
      CoffeeScript.compile "[@#{v}...] = x"

test "#2055: destructuring assignment with `new`", ->
  {length} = new Array
  eq 0, length

test "#156: destructuring with expansion", ->
  array = [1..5]
  [first, ..., last] = array
  eq 1, first
  eq 5, last
  [..., lastButOne, last] = array
  eq 4, lastButOne
  eq 5, last
  [first, second, ..., last] = array
  eq 2, second
  [..., last] = 'strings as well -> x'
  eq 'x', last
  throws (-> CoffeeScript.compile "[1, ..., 3]"),        null, "prohibit expansion outside of assignment"
  throws (-> CoffeeScript.compile "[..., a, b...] = c"), null, "prohibit expansion and a splat"
  throws (-> CoffeeScript.compile "[...] = c"),          null, "prohibit lone expansion"

test "destructuring with dynamic keys", ->
  {"#{'a'}": a, """#{'b'}""": b, c} = {a: 1, b: 2, c: 3}
  eq 1, a
  eq 2, b
  eq 3, c
  throws -> CoffeeScript.compile '{"#{a}"} = b'


# Existential Assignment

test "existential assignment", ->
  nonce = {}
  a = false
  a ?= nonce
  eq false, a
  b = undefined
  b ?= nonce
  eq nonce, b
  c = null
  c ?= nonce
  eq nonce, c

test "#1627: prohibit conditional assignment of undefined variables", ->
  throws (-> CoffeeScript.compile "x ?= 10"),        null, "prohibit (x ?= 10)"
  throws (-> CoffeeScript.compile "x ||= 10"),       null, "prohibit (x ||= 10)"
  throws (-> CoffeeScript.compile "x or= 10"),       null, "prohibit (x or= 10)"
  throws (-> CoffeeScript.compile "do -> x ?= 10"),  null, "prohibit (do -> x ?= 10)"
  throws (-> CoffeeScript.compile "do -> x ||= 10"), null, "prohibit (do -> x ||= 10)"
  throws (-> CoffeeScript.compile "do -> x or= 10"), null, "prohibit (do -> x or= 10)"
  doesNotThrow (-> CoffeeScript.compile "x = null; x ?= 10"),        "allow (x = null; x ?= 10)"
  doesNotThrow (-> CoffeeScript.compile "x = null; x ||= 10"),       "allow (x = null; x ||= 10)"
  doesNotThrow (-> CoffeeScript.compile "x = null; x or= 10"),       "allow (x = null; x or= 10)"
  doesNotThrow (-> CoffeeScript.compile "x = null; do -> x ?= 10"),  "allow (x = null; do -> x ?= 10)"
  doesNotThrow (-> CoffeeScript.compile "x = null; do -> x ||= 10"), "allow (x = null; do -> x ||= 10)"
  doesNotThrow (-> CoffeeScript.compile "x = null; do -> x or= 10"), "allow (x = null; do -> x or= 10)"

  throws (-> CoffeeScript.compile "-> -> -> x ?= 10"), null, "prohibit (-> -> -> x ?= 10)"
  doesNotThrow (-> CoffeeScript.compile "x = null; -> -> -> x ?= 10"), "allow (x = null; -> -> -> x ?= 10)"

test "more existential assignment", ->
  global.temp ?= 0
  eq global.temp, 0
  global.temp or= 100
  eq global.temp, 100
  delete global.temp

test "#1348, #1216: existential assignment compilation", ->
  nonce = {}
  a = nonce
  b = (a ?= 0)
  eq nonce, b
  #the first ?= compiles into a statement; the second ?= compiles to a ternary expression
  eq a ?= b ?= 1, nonce

  if a then a ?= 2 else a = 3
  eq a, nonce

test "#1591, #1101: splatted expressions in destructuring assignment must be assignable", ->
  nonce = {}
  for nonref in ['', '""', '0', 'f()', '(->)'].concat CoffeeScript.RESERVED
    eq nonce, (try CoffeeScript.compile "[#{nonref}...] = v" catch e then nonce)

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']
  for access in accesses
    for i,j in [1,2,3] #position can matter
      code =
        """
        nonce = {}; nonce2 = {}; nonce3 = {};
        @o = o = new (class C then a:{}); f = -> o
        [#{new Array(i).join('x,')}#{access}...] = [#{new Array(i).join('0,')}nonce, nonce2, nonce3]
        unless #{access}[0] is nonce and #{access}[1] is nonce2 and #{access}[2] is nonce3 then throw new Error('[...]')
        """
      eq nonce, unless (try CoffeeScript.run code, bare: true catch e then true) then nonce
  # subpatterns like `[[a]...]` and `[{a}...]`
  subpatterns = ['[sub, sub2, sub3]', '{0: sub, 1: sub2, 2: sub3}']
  for subpattern in subpatterns
    for i,j in [1,2,3]
      code =
        """
        nonce = {}; nonce2 = {}; nonce3 = {};
        [#{new Array(i).join('x,')}#{subpattern}...] = [#{new Array(i).join('0,')}nonce, nonce2, nonce3]
        unless sub is nonce and sub2 is nonce2 and sub3 is nonce3 then throw new Error('[sub...]')
        """
      eq nonce, unless (try CoffeeScript.run code, bare: true catch e then true) then nonce

test "#1838: Regression with variable assignment", ->
  name =
  'dave'

  eq name, 'dave'

test '#2211: splats in destructured parameters', ->
  doesNotThrow -> CoffeeScript.compile '([a...]) ->'
  doesNotThrow -> CoffeeScript.compile '([a...],b) ->'
  doesNotThrow -> CoffeeScript.compile '([a...],[b...]) ->'
  throws -> CoffeeScript.compile '([a...,[a...]]) ->'
  doesNotThrow -> CoffeeScript.compile '([a...,[b...]]) ->'

test '#2213: invocations within destructured parameters', ->
  throws -> CoffeeScript.compile '([a()])->'
  throws -> CoffeeScript.compile '([a:b()])->'
  throws -> CoffeeScript.compile '([a:b.c()])->'
  throws -> CoffeeScript.compile '({a()})->'
  throws -> CoffeeScript.compile '({a:b()})->'
  throws -> CoffeeScript.compile '({a:b.c()})->'

test '#2532: compound assignment with terminator', ->
  doesNotThrow -> CoffeeScript.compile """
  a = "hello"
  a +=
  "
  world
  !
  "
  """

test "#2613: parens on LHS of destructuring", ->
  a = {}
  [(a).b] = [1, 2, 3]
  eq a.b, 1

test "#2181: conditional assignment as a subexpression", ->
  a = false
  false && a or= true
  eq false, a
  eq false, not a or= true

test "#1500: Assignment to variables similar to generated variables", ->
  len = 0
  x = ((results = null; n) for n in [1, 2, 3])
  arrayEq [1, 2, 3], x
  eq 0, len

  for x in [1, 2, 3]
    f = ->
      i = 0
    f()
    eq 'undefined', typeof i

  ref = 2
  x = ref * 2 ? 1
  eq x, 4
  eq 'undefined', typeof ref1

  x = {}
  base = -> x
  name = -1
  base()[-name] ?= 2
  eq x[1], 2
  eq base(), x
  eq name, -1

  f = (@a, a) -> [@a, a]
  arrayEq [1, 2], f.call scope = {}, 1, 2
  eq 1, scope.a

  doesNotThrow -> CoffeeScript.compile '(@slice...) ->'

test "Assignment to variables similar to helper functions", ->
  f = (slice...) -> slice
  arrayEq [1, 2, 3], f 1, 2, 3
  eq 'undefined', typeof slice1

  class A
  class B extends A
    extend = 3
    hasProp = 4
    value: 5
    method: (bind, bind1) => [bind, bind1, extend, hasProp, @value]
  {method} = new B
  arrayEq [1, 2, 3, 4, 5], method 1, 2

  modulo = -1 %% 3
  eq 2, modulo

  indexOf = [1, 2, 3]
  ok 2 in indexOf
1.9.3~dfsg/test/sourcemap.coffee0000644000000000000000000000235712531364553015432 0ustar  rootrootreturn if global.testingBrowser

SourceMap = require '../src/sourcemap'

vlqEncodedValues = [
    [1, "C"],
    [-1, "D"],
    [2, "E"],
    [-2, "F"],
    [0, "A"],
    [16, "gB"],
    [948, "o7B"]
]

test "encodeVlq tests", ->
  for pair in vlqEncodedValues
    eq ((new SourceMap).encodeVlq pair[0]), pair[1]

eqJson = (a, b) ->
  eq (JSON.stringify JSON.parse a), (JSON.stringify JSON.parse b)

test "SourceMap tests", ->
  map = new SourceMap
  map.add [0, 0], [0, 0]
  map.add [1, 5], [2, 4]
  map.add [1, 6], [2, 7]
  map.add [1, 9], [2, 8]
  map.add [3, 0], [3, 4]

  testWithFilenames = map.generate {
        sourceRoot: "",
        sourceFiles: ["source.coffee"],
        generatedFile: "source.js"}
  eqJson testWithFilenames, '{"version":3,"file":"source.js","sourceRoot":"","sources":["source.coffee"],"names":[],"mappings":"AAAA;;IACK,GAAC,CAAG;IAET"}'
  eqJson map.generate(), '{"version":3,"file":"","sourceRoot":"","sources":[""],"names":[],"mappings":"AAAA;;IACK,GAAC,CAAG;IAET"}'

  # Look up a generated column - should get back the original source position.
  arrayEq map.sourceLocation([2,8]), [1,9]

  # Look up a point further along on the same line - should get back the same source position.
  arrayEq map.sourceLocation([2,10]), [1,9]
1.9.3~dfsg/test/numbers.coffee0000644000000000000000000000343612531364553015106 0ustar  rootroot# Number Literals
# ---------------

# * Decimal Integer Literals
# * Octal Integer Literals
# * Hexadecimal Integer Literals
# * Scientific Notation Integer Literals
# * Scientific Notation Non-Integer Literals
# * Non-Integer Literals
# * Binary Integer Literals


# Binary Integer Literals
# Binary notation is understood as would be decimal notation.

test "Parser recognises binary numbers", ->
  eq 4, 0b100

# Decimal Integer Literals

test "call methods directly on numbers", ->
  eq 4, 4.valueOf()
  eq '11', 4.toString 3

eq -1, 3 -4

#764: Numbers should be indexable
eq Number::toString, 42['toString']

eq Number::toString, 42.toString


# Non-Integer Literals

# Decimal number literals.
value = .25 + .75
ok value is 1
value = 0.0 + -.25 - -.75 + 0.0
ok value is 0.5

#764: Numbers should be indexable
eq Number::toString,   4['toString']
eq Number::toString, 4.2['toString']
eq Number::toString, .42['toString']
eq Number::toString, (4)['toString']

eq Number::toString,   4.toString
eq Number::toString, 4.2.toString
eq Number::toString, .42.toString
eq Number::toString, (4).toString

test '#1168: leading floating point suppresses newline', ->
  eq 1, do ->
    1
    .5 + 0.5

test "Python-style octal literal notation '0o777'", ->
  eq 511, 0o777
  eq 1, 0o1
  eq 1, 0o00001
  eq parseInt('0777', 8), 0o777
  eq '777', 0o777.toString 8
  eq 4, 0o4.valueOf()
  eq Number::toString, 0o777['toString']
  eq Number::toString, 0o777.toString

test "#2060: Disallow uppercase radix prefixes and exponential notation", ->
  for char in ['b', 'o', 'x', 'e']
    program = "0#{char}0"
    doesNotThrow -> CoffeeScript.compile program, bare: yes
    throws -> CoffeeScript.compile program.toUpperCase(), bare: yes

test "#2224: hex literals with 0b or B or E", ->
  eq 176, 0x0b0
  eq 177, 0x0B1
  eq 225, 0xE1
1.9.3~dfsg/test/regexps.coffee0000644000000000000000000001306212531364553015104 0ustar  rootroot# Regular Expression Literals
# ---------------------------

# TODO: add method invocation tests: /regex/.toString()

# * Regexen
# * Heregexen

test "basic regular expression literals", ->
  ok 'a'.match(/a/)
  ok 'a'.match /a/
  ok 'a'.match(/a/g)
  ok 'a'.match /a/g

test "division is not confused for a regular expression", ->
  # Any spacing around the slash is allowed when it cannot be a regex.
  eq 2, 4 / 2 / 1
  eq 2, 4/2/1
  eq 2, 4/ 2 / 1
  eq 2, 4 /2 / 1
  eq 2, 4 / 2/ 1
  eq 2, 4 / 2 /1
  eq 2, 4 /2/ 1

  a = (regex) -> regex.test 'a b c'
  a.valueOf = -> 4
  b = 2
  g = 1

  eq 2, a / b/g
  eq 2, a/ b/g
  eq 2, a / b/ g
  eq 2, a	/	b/g # Tabs.
  eq 2, a / b/g # Non-breaking spaces.
  eq true, a /b/g
  # Use parentheses to disambiguate.
  eq true, a(/ b/g)
  eq true, a(/ b/)
  eq true, a (/ b/)
  # Escape to disambiguate.
  eq true, a /\ b/g
  eq false, a	/\	b/g
  eq true, a /\ b/

  obj = method: -> 2
  two = 2
  eq 2, (obj.method()/two + obj.method()/two)

  i = 1
  eq 2, (4)/2/i
  eq 1, i/i/i

  a = ''
  a += ' ' until /   /.test a
  eq a, '   '

  a = if /=/.test '=' then yes else no
  eq a, yes

  a = if !/=/.test '=' then yes else no
  eq a, no

  #3182:
  match = 'foo=bar'.match /=/
  eq match[0], '='

  #3410:
  ok ' '.match(/ /)[0] is ' '


test "division vs regex after a callable token", ->
  b = 2
  g = 1
  r = (r) -> r.test 'b'

  a = 4
  eq 2, a / b/g
  eq 2, a/b/g
  eq 2, a/ b/g
  eq true, r /b/g
  eq 2, (1 + 3) / b/g
  eq 2, (1 + 3)/b/g
  eq 2, (1 + 3)/ b/g
  eq true, (r) /b/g
  eq 2, [4][0] / b/g
  eq 2, [4][0]/b/g
  eq 2, [4][0]/ b/g
  eq true, [r][0] /b/g
  eq 0.5, 4? / b/g
  eq 0.5, 4?/b/g
  eq 0.5, 4?/ b/g
  eq true, r? /b/g
  (->
    eq 2, @ / b/g
    eq 2, @/b/g
    eq 2, @/ b/g
  ).call 4
  (->
    eq true, @ /b/g
  ).call r
  (->
    eq 2, this / b/g
    eq 2, this/b/g
    eq 2, this/ b/g
  ).call 4
  (->
    eq true, this /b/g
  ).call r
  class A
    p: (regex) -> if regex then r regex else 4
  class B extends A
    p: ->
      eq 2, super / b/g
      eq 2, super/b/g
      eq 2, super/ b/g
      eq true, super /b/g
  new B().p()

test "always division and never regex after some tokens", ->
  b = 2
  g = 1

  eq 2, 4 / b/g
  eq 2, 4/b/g
  eq 2, 4/ b/g
  eq 2, 4 /b/g
  eq 2, "4" / b/g
  eq 2, "4"/b/g
  eq 2, "4"/ b/g
  eq 2, "4" /b/g
  eq 20, "4#{0}" / b/g
  eq 20, "4#{0}"/b/g
  eq 20, "4#{0}"/ b/g
  eq 20, "4#{0}" /b/g
  ok isNaN /a/ / b/g
  ok isNaN /a/i / b/g
  ok isNaN /a//b/g
  ok isNaN /a/i/b/g
  ok isNaN /a// b/g
  ok isNaN /a/i/ b/g
  ok isNaN /a/ /b/g
  ok isNaN /a/i /b/g
  eq 0.5, true / b/g
  eq 0.5, true/b/g
  eq 0.5, true/ b/g
  eq 0.5, true /b/g
  eq 0, false / b/g
  eq 0, false/b/g
  eq 0, false/ b/g
  eq 0, false /b/g
  eq 0, null / b/g
  eq 0, null/b/g
  eq 0, null/ b/g
  eq 0, null /b/g
  ok isNaN undefined / b/g
  ok isNaN undefined/b/g
  ok isNaN undefined/ b/g
  ok isNaN undefined /b/g
  ok isNaN {a: 4} / b/g
  ok isNaN {a: 4}/b/g
  ok isNaN {a: 4}/ b/g
  ok isNaN {a: 4} /b/g
  o = prototype: 4
  eq 2, o:: / b/g
  eq 2, o::/b/g
  eq 2, o::/ b/g
  eq 2, o:: /b/g
  i = 4
  eq 2.0, i++ / b/g
  eq 2.5, i++/b/g
  eq 3.0, i++/ b/g
  eq 3.5, i++ /b/g
  eq 4.0, i-- / b/g
  eq 3.5, i--/b/g
  eq 3.0, i--/ b/g
  eq 2.5, i-- /b/g

test "compound division vs regex", ->
  c = 4
  i = 2

  a = 10
  b = a /= c / i
  eq a, 5

  a = 10
  b = a /= c /i
  eq a, 5

  a = 10
  b = a	/=	c /i # Tabs.
  eq a, 5

  a = 10
  b = a /= c /i # Non-breaking spaces.
  eq a, 5

  a = 10
  b = a/= c /i
  eq a, 5

  a = 10
  b = a/=c/i
  eq a, 5

  a = (regex) -> regex.test '=C '
  b = a /=c /i
  eq b, true

  a = (regex) -> regex.test '= C '
  # Use parentheses to disambiguate.
  b = a(/= c /i)
  eq b, true
  b = a(/= c /)
  eq b, false
  b = a (/= c /)
  eq b, false
  # Escape to disambiguate.
  b = a /\= c /i
  eq b, true
  b = a /\= c /
  eq b, false

test "#764: regular expressions should be indexable", ->
  eq /0/['source'], ///#{0}///['source']

test "#584: slashes are allowed unescaped in character classes", ->
  ok /^a\/[/]b$/.test 'a//b'

test "does not allow to escape newlines", ->
  throws -> CoffeeScript.compile '/a\\\nb/'


# Heregexe(n|s)

test "a heregex will ignore whitespace and comments", ->
  eq /^I'm\x20+[a]\s+Heregex?\/\/\//gim + '', ///
    ^ I'm \x20+ [a] \s+
    Heregex? / // # or not
  ///gim + ''

test "an empty heregex will compile to an empty, non-capturing group", ->
  eq /(?:)/ + '', ///  /// + ''
  eq /(?:)/ + '', ////// + ''

test "heregex starting with slashes", ->
  ok /////a/\////.test ' //a// '

test '#2388: `///` in heregex interpolations', ->
  ok ///a#{///b///}c///.test ' /a/b/c/ '
  ws = ' \t'
  scan = (regex) -> regex.exec('\t  foo')[0]
  eq '/\t  /', /// #{scan /// [#{ws}]* ///} /// + ''

test "regexes are not callable", ->
  throws -> CoffeeScript.compile '/a/()'
  throws -> CoffeeScript.compile '///a#{b}///()'
  throws -> CoffeeScript.compile '/a/ 1'
  throws -> CoffeeScript.compile '///a#{b}/// 1'
  throws -> CoffeeScript.compile '''
    /a/
       k: v
  '''
  throws -> CoffeeScript.compile '''
    ///a#{b}///
       k: v
  '''

test "backreferences", ->
  ok /(a)(b)\2\1/.test 'abba'

test "#3795: Escape otherwise invalid characters", ->
  ok (/
/).test '\u2028'
  ok (/
/).test '\u2029'
  ok ///\
///.test '\u2028'
  ok ///\
///.test '\u2029'
  ok ///a
b///.test 'ab' # The space is U+2028.
  ok ///a
b///.test 'ab' # The space is U+2029.
  ok ///\0
      1///.test '\x001'

  a = 'a'
  ok ///#{a}
b///.test 'ab' # The space is U+2028.
  ok ///#{a}
b///.test 'ab' # The space is U+2029.
  ok ///#{a}\
///.test 'a\u2028'
  ok ///#{a}\
///.test 'a\u2029'
  ok ///#{a}\0
      1///.test 'a\x001'
1.9.3~dfsg/test/comments.coffee0000644000000000000000000001423412531364553015256 0ustar  rootroot# Comments
# --------

# * Single-Line Comments
# * Block Comments

# Note: awkward spacing seen in some tests is likely intentional.

test "comments in objects", ->
  obj1 = {
  # comment
    # comment
      # comment
    one: 1
  # comment
    two: 2
      # comment
  }

  ok Object::hasOwnProperty.call(obj1,'one')
  eq obj1.one, 1
  ok Object::hasOwnProperty.call(obj1,'two')
  eq obj1.two, 2

test "comments in YAML-style objects", ->
  obj2 =
  # comment
    # comment
      # comment
    three: 3
  # comment
    four: 4
      # comment

  ok Object::hasOwnProperty.call(obj2,'three')
  eq obj2.three, 3
  ok Object::hasOwnProperty.call(obj2,'four')
  eq obj2.four, 4

test "comments following operators that continue lines", ->
  sum =
    1 +
    1 + # comment
    1
  eq 3, sum

test "comments in functions", ->
  fn = ->
  # comment
    false
    false   # comment
    false
    # comment

  # comment
    true

  ok fn()

  fn2 = -> #comment
    fn()
    # comment

  ok fn2()

test "trailing comment before an outdent", ->
  nonce = {}
  fn3 = ->
    if true
      undefined # comment
    nonce

  eq nonce, fn3()

test "comments in a switch", ->
  nonce = {}
  result = switch nonce #comment
    # comment
    when false then undefined
    # comment
    when null #comment
      undefined
    else nonce # comment

  eq nonce, result

test "comment with conditional statements", ->
  nonce = {}
  result = if false # comment
    undefined
  #comment
  else # comment
    nonce
    # comment
  eq nonce, result

test "spaced comments with conditional statements", ->
  nonce = {}
  result = if false
    undefined

  # comment
  else if false
    undefined

  # comment
  else
    nonce

  eq nonce, result


# Block Comments

###
  This is a here-comment.
  Kind of like a heredoc.
###

test "block comments in objects", ->
  a = {}
  b = {}
  obj = {
    a: a
    ###
    comment
    ###
    b: b
  }

  eq a, obj.a
  eq b, obj.b

test "block comments in YAML-style", ->
  a = {}
  b = {}
  obj =
    a: a
    ###
    comment
    ###
    b: b

  eq a, obj.a
  eq b, obj.b


test "block comments in functions", ->
  nonce = {}

  fn1 = ->
    true
    ###
    false
    ###

  ok fn1()

  fn2 =  ->
    ###
    block comment
    ###
    nonce

  eq nonce, fn2()

  fn3 = ->
    nonce
  ###
  block comment
  ###

  eq nonce, fn3()

  fn4 = ->
    one = ->
      ###
        block comment
      ###
      two = ->
        three = ->
          nonce

  eq nonce, fn4()()()()

test "block comments inside class bodies", ->
  class A
    a: ->

    ###
    Comment
    ###
    b: ->

  ok A.prototype.b instanceof Function

  class B
    ###
    Comment
    ###
    a: ->
    b: ->

  ok B.prototype.a instanceof Function

test "#2037: herecomments shouldn't imply line terminators", ->
  do (-> ### ###; fail)

test "#2916: block comment before implicit call with implicit object", ->
  fn = (obj) -> ok obj.a
  ### ###
  fn
    a: yes

test "#3132: Format single-line block comment nicely", ->
  input = """
  ### Single-line block comment without additional space here => ###"""

  result = """

  /* Single-line block comment without additional space here => */


  """
  eq CoffeeScript.compile(input, bare: on), result

test "#3132: Format multi-line block comment nicely", ->
  input = """
  ###
  # Multi-line
  # block
  # comment
  ###"""

  result = """

  /*
   * Multi-line
   * block
   * comment
   */


  """
  eq CoffeeScript.compile(input, bare: on), result

test "#3132: Format simple block comment nicely", ->
  input = """
  ###
  No
  Preceding hash
  ###"""

  result = """

  /*
  No
  Preceding hash
   */


  """

  eq CoffeeScript.compile(input, bare: on), result

test "#3132: Format indented block-comment nicely", ->
  input = """
  fn = () ->
    ###
    # Indented
    Multiline
    ###
    1"""

  result = """
  var fn;

  fn = function() {

    /*
     * Indented
    Multiline
     */
    return 1;
  };

  """
  eq CoffeeScript.compile(input, bare: on), result

# Although adequately working, block comment-placement is not yet perfect.
# (Considering a case where multiple variables have been declared …)
test "#3132: Format jsdoc-style block-comment nicely", ->
  input = """
  ###*
  # Multiline for jsdoc-"@doctags"
  # 
  # @type {Function}
  ###
  fn = () -> 1
  """

  result = """
  
  /**
   * Multiline for jsdoc-"@doctags"
   * 
   * @type {Function}
   */
  var fn;
  
  fn = function() {
    return 1;
  };
  
  """
  eq CoffeeScript.compile(input, bare: on), result

# Although adequately working, block comment-placement is not yet perfect.
# (Considering a case where multiple variables have been declared …)
test "#3132: Format hand-made (raw) jsdoc-style block-comment nicely", ->
  input = """
  ###*
   * Multiline for jsdoc-"@doctags"
   * 
   * @type {Function}
  ###
  fn = () -> 1
  """

  result = """
  
  /**
   * Multiline for jsdoc-"@doctags"
   * 
   * @type {Function}
   */
  var fn;
  
  fn = function() {
    return 1;
  };
  
  """
  eq CoffeeScript.compile(input, bare: on), result

# Although adequately working, block comment-placement is not yet perfect.
# (Considering a case where multiple variables have been declared …)
test "#3132: Place block-comments nicely", ->
  input = """
  ###*
  # A dummy class definition
  # 
  # @class
  ###
  class DummyClass
    
    ###*
    # @constructor
    ###
    constructor: ->
  
    ###*
    # Singleton reference
    # 
    # @type {DummyClass}
    ###
    @instance = new DummyClass()
  
  """

  result = """
  
  /**
   * A dummy class definition
   * 
   * @class
   */
  var DummyClass;
  
  DummyClass = (function() {
  
    /**
     * @constructor
     */
    function DummyClass() {}
  
  
    /**
     * Singleton reference
     * 
     * @type {DummyClass}
     */
  
    DummyClass.instance = new DummyClass();
  
    return DummyClass;
  
  })();
  
  """
  eq CoffeeScript.compile(input, bare: on), result

test "#3638: Demand a whitespace after # symbol", ->
  input = """
  ###
  #No
  #whitespace
  ###"""

  result = """

  /*
  #No
  #whitespace
   */


  """

  eq CoffeeScript.compile(input, bare: on), result

test "#3761: Multiline comment at end of an object", ->
  anObject =
    x: 3
    ###
    #Comment
    ###

  ok anObject.x is 3
1.9.3~dfsg/test/scope.coffee0000644000000000000000000000475512531364553014551 0ustar  rootroot# Scope
# -----

# * Variable Safety
# * Variable Shadowing
# * Auto-closure (`do`)
# * Global Scope Leaks

test "reference `arguments` inside of functions", ->
  sumOfArgs = ->
    sum = (a,b) -> a + b
    sum = 0
    sum += num for num in arguments
    sum
  eq 10, sumOfArgs(0, 1, 2, 3, 4)

test "assignment to an Object.prototype-named variable should not leak to outer scope", ->
  # FIXME: fails on IE
  (->
    constructor = 'word'
  )()
  ok constructor isnt 'word'

test "siblings of splat parameters shouldn't leak to surrounding scope", ->
  x = 10
  oops = (x, args...) ->
  oops(20, 1, 2, 3)
  eq x, 10

test "catch statements should introduce their argument to scope", ->
  try throw ''
  catch e
    do -> e = 5
    eq 5, e

test "loop variable should be accessible after for-of loop", ->
  d = (x for x of {1:'a',2:'b'})
  ok x in ['1','2']

test "loop variable should be accessible after for-in loop", ->
  d = (x for x in [1,2])
  eq x, 2

class Array then slice: fail # needs to be global
class Object then hasOwnProperty: fail
test "#1973: redefining Array/Object constructors shouldn't confuse __X helpers", ->
  arr = [1..4]
  arrayEq [3, 4], arr[2..]
  obj = {arr}
  for own k of obj
    eq arr, obj[k]

test "#2255: global leak with splatted @-params", ->
  ok not x?
  arrayEq [0], ((@x...) -> @x).call {}, 0
  ok not x?

test "#1183: super + fat arrows", ->
  dolater = (cb) -> cb()

  class A
  	constructor: ->
  		@_i = 0
  	foo : (cb) ->
  		dolater => 
  			@_i += 1 
  			cb()

  class B extends A
  	constructor : ->
  		super
  	foo : (cb) ->
  		dolater =>
  			dolater =>
  				@_i += 2
  				super cb
          
  b = new B
  b.foo => eq b._i, 3

test "#1183: super + wrap", ->
  class A
    m : -> 10
    
  class B extends A
    constructor : -> super
    
  B::m = -> r = try super()
  
  eq (new B).m(), 10

test "#1183: super + closures", ->
  class A
    constructor: ->
      @i = 10
    foo : -> @i
    
  class B extends A
    foo : ->
      ret = switch 1
        when 0 then 0
        when 1 then super()
      ret
  eq (new B).foo(), 10
 
test "#2331: bound super regression", ->
  class A
    @value = 'A'
    method: -> @constructor.value
    
  class B extends A
    method: => super
  
  eq (new B).method(), 'A'

test "#3259: leak with @-params within destructured parameters", ->
  fn = ({@foo}, [@bar], [{@baz}]) ->
    foo = bar = baz = false

  fn.call {}, {foo: 'foo'}, ['bar'], [{baz: 'baz'}]

  eq 'undefined', typeof foo
  eq 'undefined', typeof bar
  eq 'undefined', typeof baz
1.9.3~dfsg/test/javascript_literals.coffee0000644000000000000000000000032512531364553017472 0ustar  rootroot# Javascript Literals
# -------------------

# TODO: refactor javascript literal tests
# TODO: add indexing and method invocation tests: `[1]`[0] is 1, `function(){}`.call()

eq '\\`', `
  // Inline JS
  "\\\`"
`
1.9.3~dfsg/test/comprehensions.coffee0000644000000000000000000002740312531364553016467 0ustar  rootroot# Comprehensions
# --------------

# * Array Comprehensions
# * Range Comprehensions
# * Object Comprehensions
# * Implicit Destructuring Assignment
# * Comprehensions with Nonstandard Step

# TODO: refactor comprehension tests

test "Basic array comprehensions.", ->

  nums    = (n * n for n in [1, 2, 3] when n & 1)
  results = (n * 2 for n in nums)

  ok results.join(',') is '2,18'


test "Basic object comprehensions.", ->

  obj   = {one: 1, two: 2, three: 3}
  names = (prop + '!' for prop of obj)
  odds  = (prop + '!' for prop, value of obj when value & 1)

  ok names.join(' ') is "one! two! three!"
  ok odds.join(' ')  is "one! three!"


test "Basic range comprehensions.", ->

  nums = (i * 3 for i in [1..3])

  negs = (x for x in [-20..-5*2])
  negs = negs[0..2]

  result = nums.concat(negs).join(', ')

  ok result is '3, 6, 9, -20, -19, -18'


test "With range comprehensions, you can loop in steps.", ->

  results = (x for x in [0...15] by 5)
  ok results.join(' ') is '0 5 10'

  results = (x for x in [0..100] by 10)
  ok results.join(' ') is '0 10 20 30 40 50 60 70 80 90 100'


test "And can loop downwards, with a negative step.", ->

  results = (x for x in [5..1])

  ok results.join(' ') is '5 4 3 2 1'
  ok results.join(' ') is [(10-5)..(-2+3)].join(' ')

  results = (x for x in [10..1])
  ok results.join(' ') is [10..1].join(' ')

  results = (x for x in [10...0] by -2)
  ok results.join(' ') is [10, 8, 6, 4, 2].join(' ')


test "Range comprehension gymnastics.", ->

  eq "#{i for i in [5..1]}", '5,4,3,2,1'
  eq "#{i for i in [5..-5] by -5}", '5,0,-5'

  a = 6
  b = 0
  c = -2

  eq "#{i for i in [a..b]}", '6,5,4,3,2,1,0'
  eq "#{i for i in [a..b] by c}", '6,4,2,0'


test "Multiline array comprehension with filter.", ->

  evens = for num in [1, 2, 3, 4, 5, 6] when not (num & 1)
             num *= -1
             num -= 2
             num * -1
  eq evens + '', '4,6,8'


  test "The in operator still works, standalone.", ->

    ok 2 of evens


test "all isn't reserved.", ->

  all = 1


test "Ensure that the closure wrapper preserves local variables.", ->

  obj = {}

  for method in ['one', 'two', 'three'] then do (method) ->
    obj[method] = ->
      "I'm " + method

  ok obj.one()   is "I'm one"
  ok obj.two()   is "I'm two"
  ok obj.three() is "I'm three"


test "Index values at the end of a loop.", ->

  i = 0
  for i in [1..3]
    -> 'func'
    break if false
  ok i is 4


test "Ensure that local variables are closed over for range comprehensions.", ->

  funcs = for i in [1..3]
    do (i) ->
      -> -i

  eq (func() for func in funcs).join(' '), '-1 -2 -3'
  ok i is 4


test "Even when referenced in the filter.", ->

  list = ['one', 'two', 'three']

  methods = for num, i in list when num isnt 'two' and i isnt 1
    do (num, i) ->
      -> num + ' ' + i

  ok methods.length is 2
  ok methods[0]() is 'one 0'
  ok methods[1]() is 'three 2'


test "Even a convoluted one.", ->

  funcs = []

  for i in [1..3]
    do (i) ->
      x = i * 2
      ((z)->
        funcs.push -> z + ' ' + i
      )(x)

  ok (func() for func in funcs).join(', ') is '2 1, 4 2, 6 3'

  funcs = []

  results = for i in [1..3]
    do (i) ->
      z = (x * 3 for x in [1..i])
      ((a, b, c) -> [a, b, c].join(' ')).apply this, z

  ok results.join(', ') is '3  , 3 6 , 3 6 9'


test "Naked ranges are expanded into arrays.", ->

  array = [0..10]
  ok(num % 2 is 0 for num in array by 2)


test "Nested shared scopes.", ->

  foo = ->
    for i in [0..7]
      do (i) ->
        for j in [0..7]
          do (j) ->
            -> i + j

  eq foo()[3][4](), 7


test "Scoped loop pattern matching.", ->

  a = [[0], [1]]
  funcs = []

  for [v] in a
    do (v) ->
      funcs.push -> v

  eq funcs[0](), 0
  eq funcs[1](), 1


test "Nested comprehensions.", ->

  multiLiner =
    for x in [3..5]
      for y in [3..5]
        [x, y]

  singleLiner =
    (([x, y] for y in [3..5]) for x in [3..5])

  ok multiLiner.length is singleLiner.length
  ok 5 is multiLiner[2][2][1]
  ok 5 is singleLiner[2][2][1]


test "Comprehensions within parentheses.", ->

  result = null
  store = (obj) -> result = obj
  store (x * 2 for x in [3, 2, 1])

  ok result.join(' ') is '6 4 2'


test "Closure-wrapped comprehensions that refer to the 'arguments' object.", ->

  expr = ->
    result = (item * item for item in arguments)

  ok expr(2, 4, 8).join(' ') is '4 16 64'


test "Fast object comprehensions over all properties, including prototypal ones.", ->

  class Cat
    constructor: -> @name = 'Whiskers'
    breed: 'tabby'
    hair:  'cream'

  whiskers = new Cat
  own = (value for own key, value of whiskers)
  all = (value for key, value of whiskers)

  ok own.join(' ') is 'Whiskers'
  ok all.sort().join(' ') is 'Whiskers cream tabby'


test "Optimized range comprehensions.", ->

  exxes = ('x' for [0...10])
  ok exxes.join(' ') is 'x x x x x x x x x x'


test "#3671: Allow step in optimized range comprehensions.", ->

  exxes = ('x' for [0...10] by 2)
  eq exxes.join(' ') , 'x x x x x'


test "#3671: Disallow guard in optimized range comprehensions.", ->

  throws -> CoffeeScript.compile "exxes = ('x' for [0...10] when a)"


test "Loop variables should be able to reference outer variables", ->
  outer = 1
  do ->
    null for outer in [1, 2, 3]
  eq outer, 3


test "Lenient on pure statements not trying to reach out of the closure", ->

  val = for i in [1]
    for j in [] then break
    i
  ok val[0] is i


test "Comprehensions only wrap their last line in a closure, allowing other lines
  to have pure expressions in them.", ->

  func = -> for i in [1]
    break if i is 2
    j for j in [1]

  ok func()[0][0] is 1

  i = 6
  odds = while i--
    continue unless i & 1
    i

  ok odds.join(', ') is '5, 3, 1'


test "Issue #897: Ensure that plucked function variables aren't leaked.", ->

  facets = {}
  list = ['one', 'two']

  (->
    for entity in list
      facets[entity] = -> entity
  )()

  eq typeof entity, 'undefined'
  eq facets['two'](), 'two'


test "Issue #905. Soaks as the for loop subject.", ->

  a = {b: {c: [1, 2, 3]}}
  for d in a.b?.c
    e = d

  eq e, 3


test "Issue #948. Capturing loop variables.", ->

  funcs = []
  list  = ->
    [1, 2, 3]

  for y in list()
    do (y) ->
      z = y
      funcs.push -> "y is #{y} and z is #{z}"

  eq funcs[1](), "y is 2 and z is 2"


test "Cancel the comprehension if there's a jump inside the loop.", ->

  result = try
    for i in [0...10]
      continue if i < 5
    i

  eq result, 10


test "Comprehensions over break.", ->

  arrayEq (break for [1..10]), []


test "Comprehensions over continue.", ->

  arrayEq (continue for [1..10]), []


test "Comprehensions over function literals.", ->

  a = 0
  for f in [-> a = 1]
    do (f) ->
      do f

  eq a, 1


test "Comprehensions that mention arguments.", ->

  list = [arguments: 10]
  args = for f in list
    do (f) ->
      f.arguments
  eq args[0], 10


test "expression conversion under explicit returns", ->
  nonce = {}
  fn = ->
    return (nonce for x in [1,2,3])
  arrayEq [nonce,nonce,nonce], fn()
  fn = ->
    return [nonce for x in [1,2,3]][0]
  arrayEq [nonce,nonce,nonce], fn()
  fn = ->
    return [(nonce for x in [1..3])][0]
  arrayEq [nonce,nonce,nonce], fn()


test "implicit destructuring assignment in object of objects", ->
  a={}; b={}; c={}
  obj = {
    a: { d: a },
    b: { d: b }
    c: { d: c }
  }
  result = ([y,z] for y, { d: z } of obj)
  arrayEq [['a',a],['b',b],['c',c]], result


test "implicit destructuring assignment in array of objects", ->
  a={}; b={}; c={}; d={}; e={}; f={}
  arr = [
    { a: a, b: { c: b } },
    { a: c, b: { c: d } },
    { a: e, b: { c: f } }
  ]
  result = ([y,z] for { a: y, b: { c: z } } in arr)
  arrayEq [[a,b],[c,d],[e,f]], result


test "implicit destructuring assignment in array of arrays", ->
  a={}; b={}; c={}; d={}; e={}; f={}
  arr = [[a, [b]], [c, [d]], [e, [f]]]
  result = ([y,z] for [y, [z]] in arr)
  arrayEq [[a,b],[c,d],[e,f]], result

test "issue #1124: don't assign a variable in two scopes", ->
  lista = [1, 2, 3, 4, 5]
  listb = (_i + 1 for _i in lista)
  arrayEq [2, 3, 4, 5, 6], listb

test "#1326: `by` value is uncached", ->
  a = [0,1,2]
  fi = gi = hi = 0
  f = -> ++fi
  g = -> ++gi
  h = -> ++hi

  forCompile = []
  rangeCompileSimple = []

  #exercises For.compile
  for v, i in a by f()
    forCompile.push i

  #exercises Range.compileSimple
  rangeCompileSimple = (i for i in [0..2] by g())

  arrayEq a, forCompile
  arrayEq a, rangeCompileSimple
  #exercises Range.compile
  eq "#{i for i in [0..2] by h()}", '0,1,2'

test "#1669: break/continue should skip the result only for that branch", ->
  ns = for n in [0..99]
    if n > 9
      break
    else if n & 1
      continue
    else
      n
  eq "#{ns}", '0,2,4,6,8'

  # `else undefined` is implied.
  ns = for n in [1..9]
    if n % 2
      continue unless n % 5
      n
  eq "#{ns}", "1,,3,,,7,,9"

  # Ditto.
  ns = for n in [1..9]
    switch
      when n % 2
        continue unless n % 5
        n
  eq "#{ns}", "1,,3,,,7,,9"

test "#1850: inner `for` should not be expression-ized if `return`ing", ->
  eq '3,4,5', do ->
    for a in [1..9] then \
    for b in [1..9]
      c = Math.sqrt a*a + b*b
      return String [a, b, c] unless c % 1

test "#1910: loop index should be mutable within a loop iteration and immutable between loop iterations", ->
  n = 1
  iterations = 0
  arr = [0..n]
  for v, k in arr
    ++iterations
    v = k = 5
    eq 5, k
  eq 2, k
  eq 2, iterations

  iterations = 0
  for v in [0..n]
    ++iterations
  eq 2, k
  eq 2, iterations

  arr = ([v, v + 1] for v in [0..5])
  iterations = 0
  for [v0, v1], k in arr when v0
    k += 3
    ++iterations
  eq 6, k
  eq 5, iterations

test "#2007: Return object literal from comprehension", ->
  y = for x in [1, 2]
    foo: "foo" + x
  eq 2, y.length
  eq "foo1", y[0].foo
  eq "foo2", y[1].foo

  x = 2
  y = while x
    x: --x
  eq 2, y.length
  eq 1, y[0].x
  eq 0, y[1].x

test "#2274: Allow @values as loop variables", ->
  obj = {
    item: null
    method: ->
      for @item in [1, 2, 3]
        null
  }
  eq obj.item, null
  obj.method()
  eq obj.item, 3

test "#2525, #1187, #1208, #1758, looping over an array forwards", ->
  list = [0, 1, 2, 3, 4]

  ident = (x) -> x

  arrayEq (i for i in list), list

  arrayEq (index for i, index in list), list

  arrayEq (i for i in list by 1), list

  arrayEq (i for i in list by ident 1), list

  arrayEq (i for i in list by ident(1) * 2), [0, 2, 4]

  arrayEq (index for i, index in list by ident(1) * 2), [0, 2, 4]

test "#2525, #1187, #1208, #1758, looping over an array backwards", ->
  list = [0, 1, 2, 3, 4]
  backwards = [4, 3, 2, 1, 0]

  ident = (x) -> x

  arrayEq (i for i in list by -1), backwards

  arrayEq (index for i, index in list by -1), backwards

  arrayEq (i for i in list by ident -1), backwards

  arrayEq (i for i in list by ident(-1) * 2), [4, 2, 0]

  arrayEq (index for i, index in list by ident(-1) * 2), [4, 2, 0]

test "splats in destructuring in comprehensions", ->
  list = [[0, 1, 2], [2, 3, 4], [4, 5, 6]]
  arrayEq (seq for [rep, seq...] in list), [[1, 2], [3, 4], [5, 6]]

test "#156: expansion in destructuring in comprehensions", ->
  list = [[0, 1, 2], [2, 3, 4], [4, 5, 6]]
  arrayEq (last for [..., last] in list), [2, 4, 6]

test "#3778: Consistently always cache for loop range boundaries and steps, even
      if they are simple identifiers", ->
  a = 1; arrayEq [1, 2, 3], (for n in [1, 2, 3] by  a then a = 4; n)
  a = 1; arrayEq [1, 2, 3], (for n in [1, 2, 3] by +a then a = 4; n)
  a = 1; arrayEq [1, 2, 3], (for n in [a..3]          then a = 4; n)
  a = 1; arrayEq [1, 2, 3], (for n in [+a..3]         then a = 4; n)
  a = 3; arrayEq [1, 2, 3], (for n in [1..a]          then a = 4; n)
  a = 3; arrayEq [1, 2, 3], (for n in [1..+a]         then a = 4; n)
  a = 1; arrayEq [1, 2, 3], (for n in [1..3] by  a    then a = 4; n)
  a = 1; arrayEq [1, 2, 3], (for n in [1..3] by +a    then a = 4; n)
1.9.3~dfsg/test/generators.coffee0000644000000000000000000001273512531364553015606 0ustar  rootroot# Generators
# -----------------
#
# * Generator Definition

test "most basic generator support", ->
  ok -> yield 0

test "empty generator", ->
  x = do -> yield return

  y = x.next()
  ok y.value is undefined and y.done is true

test "generator iteration", ->
  x = do ->
    yield 0
    yield 1
    yield 2
  y = x.next()
  ok y.value is 0 and y.done is false

  y = x.next()
  ok y.value is 1 and y.done is false

  y = x.next()
  ok y.value is 2 and y.done is false

  y = x.next()
  ok y.value is undefined and y.done is true

test "last line yields are returned", ->
  x = do ->
    yield 3
  y = x.next()
  ok y.value is 3 and y.done is false

  y = x.next 42
  ok y.value is 42 and y.done is true

test "yield return can be used anywhere in the function body", ->
  x = do ->
    if 2 is yield 1
      yield return 42
    throw new Error "this code shouldn't be reachable"

  y = x.next()
  ok y.value is 1 and y.done is false

  y = x.next 2
  ok y.value is 42 and y.done is true

test "bound generator", ->
  obj =
    bound: ->
      do =>
        yield this
    unbound: ->
      do ->
        yield this
    nested: ->
      do =>
        yield do =>
          yield do =>
            yield this

  eq obj, obj.bound().next().value
  ok obj isnt obj.unbound().next().value
  eq obj, obj.nested().next().value.next().value.next().value

test "error if `yield` occurs outside of a function", ->
  throws -> CoffeeScript.compile 'yield 1'

test "`yield` by itself not at the end of a function errors", ->
  throws -> CoffeeScript.compile 'x = -> yield; return'

test "`yield from` support", ->
  x = do ->
    yield from do ->
      yield i for i in [3..4]

  y = x.next()
  ok y.value is 3 and y.done is false

  y = x.next 1
  ok y.value is 4 and y.done is false

  y = x.next 2
  arrayEq y.value, [1, 2]
  ok y.done is true

test "error if `yield from` occurs outside of a function", ->
  throws -> CoffeeScript.compile 'yield from 1'

test "`yield from` at the end of a function errors", ->
  throws -> CoffeeScript.compile 'x = -> x = 1; yield from'

test "yield in if statements", ->
  x = do -> if 1 is yield 2 then 3 else 4

  y = x.next()
  ok y.value is 2 and y.done is false

  y = x.next 1
  ok y.value is 3 and y.done is true

test "yielding if statements", ->
  x = do -> yield if true then 3 else 4

  y = x.next()
  ok y.value is 3 and y.done is false

  y = x.next 42
  ok y.value is 42 and y.done is true

test "yield in for loop expressions", ->
  x = do ->
    y = for i in [1..3]
      yield i * 2

  z = x.next()
  ok z.value is 2 and z.done is false

  z = x.next 10
  ok z.value is 4 and z.done is false

  z = x.next 20
  ok z.value is 6 and z.done is false

  z = x.next 30
  arrayEq z.value, [10, 20, 30]
  ok z.done is true

test "yielding for loop expressions", ->
  x = do ->
    yield for i in [1..3]
      i * 2

  y = x.next()
  arrayEq y.value, [2, 4, 6]
  ok y.done is false

  y = x.next 42
  ok y.value is 42 and y.done is true

test "yield in switch expressions", ->
  x = do ->
    y = switch yield 1
      when 2 then yield 1337
      else 1336

  z = x.next()
  ok z.value is 1 and z.done is false

  z = x.next 2
  ok z.value is 1337 and z.done is false

  z = x.next 3
  ok z.value is 3 and z.done is true

test "yielding switch expressions", ->
  x = do ->
    yield switch 1337
      when 1337 then 1338
      else 1336

  y = x.next()
  ok y.value is 1338 and y.done is false

  y = x.next 42
  ok y.value is 42 and y.done is true

test "yield in try expressions", ->
  x = do ->
    try yield 1 catch

  y = x.next()
  ok y.value is 1 and y.done is false

  y = x.next 42
  ok y.value is 42 and y.done is true

test "yielding try expressions", ->
  x = do ->
    yield try 1

  y = x.next()
  ok y.value is 1 and y.done is false

  y = x.next 42
  ok y.value is 42 and y.done is true

test "`yield` can be thrown", ->
  x = do ->
    throw yield null
  x.next()
  throws -> x.next new Error "boom"

test "`throw` can be yielded", ->
  x = do ->
    yield throw new Error "boom"
  throws -> x.next()

test "symbolic operators has precedence over the `yield`", ->
  symbolic   = '+ - * / << >> & | || && ** ^ // or and'.split ' '
  compound   = ("#{op}=" for op in symbolic)
  relations  = '< > == != <= >= is isnt'.split ' '

  operators  = [symbolic..., '=', compound..., relations...]

  collect = (gen) -> ref.value until (ref = gen.next()).done

  values = [0, 1, 2, 3]
  for op in operators
    expression = "i #{op} 2"

    yielded = CoffeeScript.eval "(arr) ->  yield #{expression} for i in arr"
    mapped  = CoffeeScript.eval "(arr) ->       (#{expression} for i in arr)"

    arrayEq mapped(values), collect yielded values

test "yield handles 'this' correctly", ->
  x = ->
    yield switch
      when true then yield => this
    yield for item in [1]
      yield => this
    yield if true then yield => this
    yield try throw yield => this
    throw yield => this

  y = x.call [1, 2, 3]

  z = y.next()
  arrayEq z.value(), [1, 2, 3]
  ok z.done is false

  z = y.next 123
  ok z.value is 123 and z.done is false

  z = y.next()
  arrayEq z.value(), [1, 2, 3]
  ok z.done is false

  z = y.next 42
  arrayEq z.value, [42]
  ok z.done is false

  z = y.next()
  arrayEq z.value(), [1, 2, 3]
  ok z.done is false

  z = y.next 456
  ok z.value is 456 and z.done is false

  z = y.next()
  arrayEq z.value(), [1, 2, 3]
  ok z.done is false

  z = y.next new Error "ignore me"
  ok z.value is undefined and z.done is false

  z = y.next()
  arrayEq z.value(), [1, 2, 3]
  ok z.done is false

  throws -> y.next new Error "boom"
1.9.3~dfsg/test/objects.coffee0000644000000000000000000002470612531364553015067 0ustar  rootroot# Object Literals
# ---------------

# TODO: refactor object literal tests
# TODO: add indexing and method invocation tests: {a}['a'] is a, {a}.a()

trailingComma = {k1: "v1", k2: 4, k3: (-> true),}
ok trailingComma.k3() and (trailingComma.k2 is 4) and (trailingComma.k1 is "v1")

ok {a: (num) -> num is 10 }.a 10

moe = {
  name:  'Moe'
  greet: (salutation) ->
    salutation + " " + @name
  hello: ->
    @['greet'] "Hello"
  10: 'number'
}
ok moe.hello() is "Hello Moe"
ok moe[10] is 'number'
moe.hello = ->
  this['greet'] "Hello"
ok moe.hello() is 'Hello Moe'

obj = {
  is:     -> yes,
  'not':  -> no,
}
ok obj.is()
ok not obj.not()

### Top-level object literal... ###
obj: 1
### ...doesn't break things. ###

# Object literals should be able to include keywords.
obj = {class: 'höt'}
obj.function = 'dog'
ok obj.class + obj.function is 'hötdog'

# Implicit objects as part of chained calls.
pluck = (x) -> x.a
eq 100, pluck pluck pluck a: a: a: 100


test "YAML-style object literals", ->
  obj =
    a: 1
    b: 2
  eq 1, obj.a
  eq 2, obj.b

  config =
    development:
      server: 'localhost'
      timeout: 10

    production:
      server: 'dreamboat'
      timeout: 1000

  ok config.development.server  is 'localhost'
  ok config.production.server   is 'dreamboat'
  ok config.development.timeout is 10
  ok config.production.timeout  is 1000

obj =
  a: 1,
  b: 2,
ok obj.a is 1
ok obj.b is 2

# Implicit objects nesting.
obj =
  options:
    value: yes
  fn: ->
    {}
    null
ok obj.options.value is yes
ok obj.fn() is null

# Implicit objects with wacky indentation:
obj =
  'reverse': (obj) ->
    Array.prototype.reverse.call obj
  abc: ->
    @reverse(
      @reverse @reverse ['a', 'b', 'c'].reverse()
    )
  one: [1, 2,
    a: 'b'
  3, 4]
  red:
    orange:
          yellow:
                  green: 'blue'
    indigo: 'violet'
  misdent: [[],
  [],
                  [],
      []]
ok obj.abc().join(' ') is 'a b c'
ok obj.one.length is 5
ok obj.one[4] is 4
ok obj.one[2].a is 'b'
ok (key for key of obj.red).length is 2
ok obj.red.orange.yellow.green is 'blue'
ok obj.red.indigo is 'violet'
ok obj.misdent.toString() is ',,,'

#542: Objects leading expression statement should be parenthesized.
{f: -> ok yes }.f() + 1

# String-keyed objects shouldn't suppress newlines.
one =
  '>!': 3
six: -> 10
ok not one.six

# Shorthand objects with property references.
obj =
  ### comment one ###
  ### comment two ###
  one: 1
  two: 2
  object: -> {@one, @two}
  list:   -> [@one, @two]
result = obj.object()
eq result.one, 1
eq result.two, 2
eq result.two, obj.list()[1]

third = (a, b, c) -> c
obj =
  one: 'one'
  two: third 'one', 'two', 'three'
ok obj.one is 'one'
ok obj.two is 'three'

test "invoking functions with implicit object literals", ->
  generateGetter = (prop) -> (obj) -> obj[prop]
  getA = generateGetter 'a'
  getArgs = -> arguments
  a = b = 30

  result = getA
    a: 10
  eq 10, result

  result = getA
    "a": 20
  eq 20, result

  result = getA a,
    b:1
  eq undefined, result

  result = getA b:1,
  a:43
  eq 43, result

  result = getA b:1,
    a:62
  eq undefined, result

  result = getA
    b:1
    a
  eq undefined, result

  result = getA
    a:
      b:2
    b:1
  eq 2, result.b

  result = getArgs
    a:1
    b
    c:1
  ok result.length is 3
  ok result[2].c is 1

  result = getA b: 13, a: 42, 2
  eq 42, result

  result = getArgs a:1, (1 + 1)
  ok result[1] is 2

  result = getArgs a:1, b
  ok result.length is 2
  ok result[1] is 30

  result = getArgs a:1, b, b:1, a
  ok result.length is 4
  ok result[2].b is 1

  throws -> CoffeeScript.compile "a = b:1, c"

test "some weird indentation in YAML-style object literals", ->
  two = (a, b) -> b
  obj = then two 1,
    1: 1
    a:
      b: ->
        fn c,
          d: e
    f: 1
  eq 1, obj[1]

test "#1274: `{} = a()` compiles to `false` instead of `a()`", ->
  a = false
  fn = -> a = true
  {} = fn()
  ok a

test "#1436: `for` etc. work as normal property names", ->
  obj = {}
  eq no, obj.hasOwnProperty 'for'
  obj.for = 'foo' of obj
  eq yes, obj.hasOwnProperty 'for'

test "#2706, Un-bracketed object as argument causes inconsistent behavior", ->
  foo = (x, y) -> y
  bar = baz: yes

  eq yes, foo x: 1, bar.baz

test "#2608, Allow inline objects in arguments to be followed by more arguments", ->
  foo = (x, y) -> y

  eq yes, foo x: 1, y: 2, yes

test "#2308, a: b = c:1", ->
  foo = a: b = c: yes
  eq b.c, yes
  eq foo.a.c, yes

test "#2317, a: b c: 1", ->
  foo = (x) -> x
  bar = a: foo c: yes
  eq bar.a.c, yes

test "#1896, a: func b, {c: d}", ->
  first = (x) -> x
  second = (x, y) -> y
  third = (x, y, z) -> z

  one = 1
  two = 2
  three = 3
  four = 4

  foo = a: second one, {c: two}
  eq foo.a.c, two

  bar = a: second one, c: two
  eq bar.a.c, two

  baz = a: second one, {c: two}, e: first first h: three
  eq baz.a.c, two

  qux = a: third one, {c: two}, e: first first h: three
  eq qux.a.e.h, three

  quux = a: third one, {c: two}, e: first(three), h: four
  eq quux.a.e, three
  eq quux.a.h, four

  corge = a: third one, {c: two}, e: second three, h: four
  eq corge.a.e.h, four

test "Implicit objects, functions and arrays", ->
  first  = (x) -> x
  second = (x, y) -> y

  foo = [
    1
    one: 1
    two: 2
    three: 3
    more:
      four: 4
      five: 5, six: 6
    2, 3, 4
    5]
  eq foo[2], 2
  eq foo[1].more.six, 6

  bar = [
    1
    first first first second 1,
      one: 1, twoandthree: twoandthree: two: 2, three: 3
      2,
    2
    one: 1
    two: 2
    three: first second ->
      no
    , ->
      3
    3
    4]
  eq bar[2], 2
  eq bar[1].twoandthree.twoandthree.two, 2
  eq bar[3].three(), 3
  eq bar[4], 3

test "#2549, Brace-less Object Literal as a Second Operand on a New Line", ->
  foo = no or
    one: 1
    two: 2
    three: 3
  eq foo.one, 1

  bar = yes and one: 1
  eq bar.one, 1

  baz = null ?
    one: 1
    two: 2
  eq baz.two, 2

test "#2757, Nested", ->
  foo =
    bar:
      one: 1,
  eq foo.bar.one, 1

  baz =
    qux:
      one: 1,
    corge:
      two: 2,
      three: three: three: 3,
    xyzzy:
      thud:
        four:
          four: 4,
      five: 5,

  eq baz.qux.one, 1
  eq baz.corge.three.three.three, 3
  eq baz.xyzzy.thud.four.four, 4
  eq baz.xyzzy.five, 5

test "#1865, syntax regression 1.1.3", ->
  foo = (x, y) -> y

  bar = a: foo (->),
    c: yes
  eq bar.a.c, yes

  baz = a: foo (->), c: yes
  eq baz.a.c, yes


test "#1322: implicit call against implicit object with block comments", ->
  ((obj, arg) ->
    eq obj.x * obj.y, 6
    ok not arg
  )
    ###
    x
    ###
    x: 2
    ### y ###
    y: 3

test "#1513: Top level bare objs need to be wrapped in parens for unary and existence ops", ->
  doesNotThrow -> CoffeeScript.run "{}?", bare: true
  doesNotThrow -> CoffeeScript.run "{}.a++", bare: true

test "#1871: Special case for IMPLICIT_END in the middle of an implicit object", ->
  result = 'result'
  ident = (x) -> x

  result = ident one: 1 if false

  eq result, 'result'

  result = ident
    one: 1
    two: 2 for i in [1..3]

  eq result.two.join(' '), '2 2 2'

test "#1871: implicit object closed by IMPLICIT_END in implicit returns", ->
  ob = do ->
    a: 1 if no
  eq ob, undefined

  # instead these return an object
  func = ->
    key:
      i for i in [1, 2, 3]

  eq func().key.join(' '), '1 2 3'

  func = ->
    key: (i for i in [1, 2, 3])

  eq func().key.join(' '), '1 2 3'

test "#1961, #1974, regression with compound assigning to an implicit object", ->

  obj = null

  obj ?=
    one: 1
    two: 2

  eq obj.two, 2

  obj = null

  obj or=
    three: 3
    four: 4

  eq obj.four, 4

test "#2207: Immediate implicit closes don't close implicit objects", ->
  func = ->
    key: for i in [1, 2, 3] then i

  eq func().key.join(' '), '1 2 3'

test "#3216: For loop declaration as a value of an implicit object", ->
  test = [0..2]
  ob =
    a: for v, i in test then i
    b: for v, i in test then i
    c: for v in test by 1 then v
    d: for v in test when true then v
  arrayEq ob.a, test
  arrayEq ob.b, test
  arrayEq ob.c, test
  arrayEq ob.d, test

test 'inline implicit object literals within multiline implicit object literals', ->
  x =
    a: aa: 0
    b: 0
  eq 0, x.b
  eq 0, x.a.aa

test "object keys with interpolations", ->
  # Simple cases.
  a = 'a'
  obj = "#{a}": yes
  eq obj.a, yes
  obj = {"#{a}": yes}
  eq obj.a, yes
  obj = {"#{a}"}
  eq obj.a, 'a'
  obj = {"#{5}"}
  eq obj[5], '5' # Note that the value is a string, just like the key.

  # Commas in implicit object.
  obj = "#{'a'}": 1, b: 2
  deepEqual obj, {a: 1, b: 2}
  obj = a: 1, "#{'b'}": 2
  deepEqual obj, {a: 1, b: 2}
  obj = "#{'a'}": 1, "#{'b'}": 2
  deepEqual obj, {a: 1, b: 2}

  # Commas in explicit object.
  obj = {"#{'a'}": 1, b: 2}
  deepEqual obj, {a: 1, b: 2}
  obj = {a: 1, "#{'b'}": 2}
  deepEqual obj, {a: 1, b: 2}
  obj = {"#{'a'}": 1, "#{'b'}": 2}
  deepEqual obj, {a: 1, b: 2}

  # Commas after key with interpolation.
  obj = {"#{'a'}": yes,}
  eq obj.a, yes
  obj = {
    "#{'a'}": 1,
    "#{'b'}": 2,
    ### herecomment ###
    "#{'c'}": 3,
  }
  deepEqual obj, {a: 1, b: 2, c: 3}
  obj =
    "#{'a'}": 1,
    "#{'b'}": 2,
    ### herecomment ###
    "#{'c'}": 3,
  deepEqual obj, {a: 1, b: 2, c: 3}
  obj =
    "#{'a'}": 1,
    "#{'b'}": 2,
    ### herecomment ###
    "#{'c'}": 3, "#{'d'}": 4,
  deepEqual obj, {a: 1, b: 2, c: 3, d: 4}

  # Key with interpolation mixed with `@prop`.
  deepEqual (-> {@a, "#{'b'}": 2}).call(a: 1), {a: 1, b: 2}

  # Evaluate only once.
  count = 0
  b = -> count++; 'b'
  obj = {"#{b()}"}
  eq obj.b, 'b'
  eq count, 1

  # Evaluation order.
  arr = []
  obj =
    a: arr.push 1
    b: arr.push 2
    "#{'c'}": arr.push 3
    "#{'d'}": arr.push 4
    e: arr.push 5
    "#{'f'}": arr.push 6
    g: arr.push 7
  arrayEq arr, [1..7]
  deepEqual obj, {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7}

  # Object starting with dynamic key.
  obj =
    "#{'a'}": 1
    b: 2
  deepEqual obj, {a: 1, b: 2}

  # Comments in implicit object.
  obj =
    ### leading comment ###
    "#{'a'}": 1

    ### middle ###

    "#{'b'}": 2
    # regular comment
    'c': 3
    ### foo ###
    d: 4
    "#{'e'}": 5
  deepEqual obj, {a: 1, b: 2, c: 3, d: 4, e: 5}

  # Comments in explicit object.
  obj = {
    ### leading comment ###
    "#{'a'}": 1

    ### middle ###

    "#{'b'}": 2
    # regular comment
    'c': 3
    ### foo ###
    d: 4
    "#{'e'}": 5
  }
  deepEqual obj, {a: 1, b: 2, c: 3, d: 4, e: 5}

  # A more complicated case.
  obj = {
    "#{'interpolated'}":
      """
        #{ '''nested''' }
      """: 123: 456
  }
  deepEqual obj,
    interpolated:
      nested:
        123: 456
1.9.3~dfsg/test/interpolation.coffee0000644000000000000000000001025512531364553016317 0ustar  rootroot# Interpolation
# -------------

# * String Interpolation
# * Regular Expression Interpolation

# String Interpolation

# TODO: refactor string interpolation tests

eq 'multiline nested "interpolations" work', """multiline #{
  "nested #{
    ok true
    "\"interpolations\""
  }"
} work"""

# Issue #923: Tricky interpolation.
eq "#{ "{" }", "{"
eq "#{ '#{}}' } }", '#{}} }'
eq "#{"'#{ ({a: "b#{1}"}['a']) }'"}", "'b1'"

# Issue #1150: String interpolation regression
eq "#{'"/'}",                '"/'
eq "#{"/'"}",                "/'"
eq "#{/'"/}",                '/\'"/'
eq "#{"'/" + '/"' + /"'/}",  '\'//"/"\'/'
eq "#{"'/"}#{'/"'}#{/"'/}",  '\'//"/"\'/'
eq "#{6 / 2}",               '3'
eq "#{6 / 2}#{6 / 2}",       '33' # parsed as division
eq "#{6 + /2}#{6/ + 2}",     '6/2}#{6/2' # parsed as a regex
eq "#{6/2}
    #{6/2}",                 '3 3' # newline cannot be part of a regex, so it's division
eq "#{/// "'/'"/" ///}",     '/"\'\\/\'"\\/"/' # heregex, stuffed with spicy characters
eq "#{/\\'/}",               "/\\\\'/"

# Issue #2321: Regex/division conflict in interpolation
eq "#{4/2}/", '2/'
curWidth = 4
eq "",   ""
throws -> CoffeeScript.compile '''
   ""'''
#                 valid regex--^^^^^^^^^^^ ^--unclosed string
eq "",   ""
eq "",  ""
eq "", ""

hello = 'Hello'
world = 'World'
ok '#{hello} #{world}!' is '#{hello} #{world}!'
ok "#{hello} #{world}!" is 'Hello World!'
ok "[#{hello}#{world}]" is '[HelloWorld]'
ok "#{hello}##{world}" is 'Hello#World'
ok "Hello #{ 1 + 2 } World" is 'Hello 3 World'
ok "#{hello} #{ 1 + 2 } #{world}" is "Hello 3 World"
ok 1 + "#{2}px" is '12px'
ok isNaN "a#{2}" * 2
ok "#{2}" is '2'
ok "#{2}#{2}" is '22'

[s, t, r, i, n, g] = ['s', 't', 'r', 'i', 'n', 'g']
ok "#{s}#{t}#{r}#{i}#{n}#{g}" is 'string'
ok "\#{s}\#{t}\#{r}\#{i}\#{n}\#{g}" is '#{s}#{t}#{r}#{i}#{n}#{g}'
ok "\#{string}" is '#{string}'

ok "\#{Escaping} first" is '#{Escaping} first'
ok "Escaping \#{in} middle" is 'Escaping #{in} middle'
ok "Escaping \#{last}" is 'Escaping #{last}'

ok "##" is '##'
ok "#{}" is ''
ok "#{}A#{} #{} #{}B#{}" is 'A  B'
ok "\\\#{}" is '\\#{}'

ok "I won ##{20} last night." is 'I won #20 last night.'
ok "I won ##{'#20'} last night." is 'I won ##20 last night.'

ok "#{hello + world}" is 'HelloWorld'
ok "#{hello + ' ' + world + '!'}" is 'Hello World!'

list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
ok "values: #{list.join(', ')}, length: #{list.length}." is 'values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, length: 10.'
ok "values: #{list.join ' '}" is 'values: 0 1 2 3 4 5 6 7 8 9'

obj = {
  name: 'Joe'
  hi: -> "Hello #{@name}."
  cya: -> "Hello #{@name}.".replace('Hello','Goodbye')
}
ok obj.hi() is "Hello Joe."
ok obj.cya() is "Goodbye Joe."

ok "With #{"quotes"}" is 'With quotes'
ok 'With #{"quotes"}' is 'With #{"quotes"}'

ok "Where is #{obj["name"] + '?'}" is 'Where is Joe?'

ok "Where is #{"the nested #{obj["name"]}"}?" is 'Where is the nested Joe?'
ok "Hello #{world ? "#{hello}"}" is 'Hello World'

ok "Hello #{"#{"#{obj["name"]}" + '!'}"}" is 'Hello Joe!'

a = """
    Hello #{ "Joe" }
    """
ok a is "Hello Joe"

a = 1
b = 2
c = 3
ok "#{a}#{b}#{c}" is '123'

result = null
stash = (str) -> result = str
stash "a #{ ('aa').replace /a/g, 'b' } c"
ok result is 'a bb c'

foo = "hello"
ok "#{foo.replace("\"", "")}" is 'hello'

val = 10
a = """
    basic heredoc #{val}
    on two lines
    """
b = '''
    basic heredoc #{val}
    on two lines
    '''
ok a is "basic heredoc 10\non two lines"
ok b is "basic heredoc \#{val}\non two lines"

eq 'multiline nested "interpolations" work', """multiline #{
  "nested #{(->
    ok yes
    "\"interpolations\""
  )()}"
} work"""

eq 'function(){}', "#{->}".replace /\s/g, ''
ok /^a[\s\S]+b$/.test "a#{=>}b"
ok /^a[\s\S]+b$/.test "a#{ (x) -> x ** 2 }b"

# Regular Expression Interpolation

# TODO: improve heregex interpolation tests

test "heregex interpolation", ->
  eq /\\#{}\\"/ + '', ///
   #{
     "#{ '\\' }" # normal comment
   }
   # regex comment
   \#{}
   \\ "
  /// + ''
1.9.3~dfsg/test/ranges.coffee0000644000000000000000000000445212531364553014711 0ustar  rootroot# Range Literals
# --------------

# TODO: add indexing and method invocation tests: [1..4][0] is 1, [0...3].toString()

# shared array
shared = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

test "basic inclusive ranges", ->
  arrayEq [1, 2, 3] , [1..3]
  arrayEq [0, 1, 2] , [0..2]
  arrayEq [0, 1]    , [0..1]
  arrayEq [0]       , [0..0]
  arrayEq [-1]      , [-1..-1]
  arrayEq [-1, 0]   , [-1..0]
  arrayEq [-1, 0, 1], [-1..1]

test "basic exclusive ranges", ->
  arrayEq [1, 2, 3] , [1...4]
  arrayEq [0, 1, 2] , [0...3]
  arrayEq [0, 1]    , [0...2]
  arrayEq [0]       , [0...1]
  arrayEq [-1]      , [-1...0]
  arrayEq [-1, 0]   , [-1...1]
  arrayEq [-1, 0, 1], [-1...2]

  arrayEq [], [1...1]
  arrayEq [], [0...0]
  arrayEq [], [-1...-1]

test "downward ranges", ->
  arrayEq shared, [9..0].reverse()
  arrayEq [5, 4, 3, 2] , [5..2]
  arrayEq [2, 1, 0, -1], [2..-1]

  arrayEq [3, 2, 1]  , [3..1]
  arrayEq [2, 1, 0]  , [2..0]
  arrayEq [1, 0]     , [1..0]
  arrayEq [0]        , [0..0]
  arrayEq [-1]       , [-1..-1]
  arrayEq [0, -1]    , [0..-1]
  arrayEq [1, 0, -1] , [1..-1]
  arrayEq [0, -1, -2], [0..-2]

  arrayEq [4, 3, 2], [4...1]
  arrayEq [3, 2, 1], [3...0]
  arrayEq [2, 1]   , [2...0]
  arrayEq [1]      , [1...0]
  arrayEq []       , [0...0]
  arrayEq []       , [-1...-1]
  arrayEq [0]      , [0...-1]
  arrayEq [0, -1]  , [0...-2]
  arrayEq [1, 0]   , [1...-1]
  arrayEq [2, 1, 0], [2...-1]

test "ranges with variables as enpoints", ->
  [a, b] = [1, 3]
  arrayEq [1, 2, 3], [a..b]
  arrayEq [1, 2]   , [a...b]
  b = -2
  arrayEq [1, 0, -1, -2], [a..b]
  arrayEq [1, 0, -1]    , [a...b]

test "ranges with expressions as endpoints", ->
  [a, b] = [1, 3]
  arrayEq [2, 3, 4, 5, 6], [(a+1)..2*b]
  arrayEq [2, 3, 4, 5]   , [(a+1)...2*b]

test "large ranges are generated with looping constructs", ->
  down = [99..0]
  eq 100, (len = down.length)
  eq   0, down[len - 1]

  up = [0...100]
  eq 100, (len = up.length)
  eq  99, up[len - 1]

test "#1012 slices with arguments object", ->
  expected = [0..9]
  argsAtStart = (-> [arguments[0]..9]) 0
  arrayEq expected, argsAtStart
  argsAtEnd = (-> [0..arguments[0]]) 9
  arrayEq expected, argsAtEnd
  argsAtBoth = (-> [arguments[0]..arguments[1]]) 0, 9
  arrayEq expected, argsAtBoth

test "#1409: creating large ranges outside of a function body", ->
  CoffeeScript.eval '[0..100]'
1.9.3~dfsg/test/formatting.coffee0000644000000000000000000001126512531364553015604 0ustar  rootroot# Formatting
# ----------

# TODO: maybe this file should be split up into their respective sections:
#   operators -> operators
#   array literals -> array literals
#   string literals -> string literals
#   function invocations -> function invocations

doesNotThrow -> CoffeeScript.compile "a = then b"

test "multiple semicolon-separated statements in parentheticals", ->
  nonce = {}
  eq nonce, (1; 2; nonce)
  eq nonce, (-> return (1; 2; nonce))()

# * Line Continuation
#   * Property Accesss
#   * Operators
#   * Array Literals
#   * Function Invocations
#   * String Literals

# Property Access

test "chained accesses split on period/newline, backwards and forwards", ->
  str = 'abc'
  result = str.
    split('').
    reverse().
    reverse().
    reverse()
  arrayEq ['c','b','a'], result
  arrayEq ['c','b','a'], str.
    split('').
    reverse().
    reverse().
    reverse()
  result = str
    .split('')
    .reverse()
    .reverse()
    .reverse()
  arrayEq ['c','b','a'], result
  arrayEq ['c','b','a'],
    str
    .split('')
    .reverse()
    .reverse()
    .reverse()
  arrayEq ['c','b','a'],
    str.
    split('')
    .reverse().
    reverse()
    .reverse()

# Operators

test "newline suppression for operators", ->
  six =
    1 +
    2 +
    3
  eq 6, six

test "`?.` and `::` should continue lines", ->
  ok not (
    Date
    ::
    ?.foo
  )
  #eq Object::toString, Date?.
  #prototype
  #::
  #?.foo

doesNotThrow -> CoffeeScript.compile """
  oh. yes
  oh?. true
  oh:: return
  """

doesNotThrow -> CoffeeScript.compile """
  a?[b..]
  a?[...b]
  a?[b..c]
  """

# Array Literals

test "indented array literals don't trigger whitespace rewriting", ->
  getArgs = -> arguments
  result = getArgs(
    [[[[[],
                  []],
                [[]]]],
      []])
  eq 1, result.length

# Function Invocations

doesNotThrow -> CoffeeScript.compile """
  obj = then fn 1,
    1: 1
    a:
      b: ->
        fn c,
          d: e
    f: 1
  """

# String Literals

test "indented heredoc", ->
  result = ((_) -> _)(
                """
                abc
                """)
  eq "abc", result

# Chaining - all open calls are closed by property access starting a new line
# * chaining after
#   * indented argument
#   * function block
#   * indented object
#
#   * single line arguments
#   * inline function literal
#   * inline object literal

test "chaining after outdent", ->
  id = (x) -> x

  # indented argument
  ff = id parseInt "ff",
    16
  .toString()
  eq '255', ff

  # function block
  str = 'abc'
  zero = parseInt str.replace /\w/, (letter) ->
    0
  .toString()
  eq '0', zero

  # indented object
  a = id id
    a: 1
  .a
  eq 1, a

test "#1495, method call chaining", ->
  str = 'abc'

  result = str.split ''
              .join ', '
  eq 'a, b, c', result

  result = str
  .split ''
  .join ', '
  eq 'a, b, c', result

  eq 'a, b, c', (str
    .split ''
    .join ', '
  )

  eq 'abc',
    'aaabbbccc'.replace /(\w)\1\1/g, '$1$1'
               .replace /([abc])\1/g, '$1'

  # Nested calls
  result = [1..3]
    .slice Math.max 0, 1
    .concat [3]
  arrayEq [2, 3, 3], result

  # Single line function arguments
  result = [1..6]
    .map (x) -> x * x
    .filter (x) -> x % 2 is 0
    .reverse()
  arrayEq [36, 16, 4], result

  # Single line implicit objects
  id = (x) -> x
  result = id a: 1
    .a
  eq 1, result

  # The parens are forced
  result = str.split(''.
    split ''
    .join ''
  ).join ', '
  eq 'a, b, c', result

# Nested blocks caused by paren unwrapping
test "#1492: Nested blocks don't cause double semicolons", ->
  js = CoffeeScript.compile '(0;0)'
  eq -1, js.indexOf ';;'

test "#1195 Ignore trailing semicolons (before newlines or as the last char in a program)", ->
  preNewline = (numSemicolons) ->
    """
    nonce = {}; nonce2 = {}
    f = -> nonce#{Array(numSemicolons+1).join(';')}
    nonce2
    unless f() is nonce then throw new Error('; before linebreak should = newline')
    """
  CoffeeScript.run(preNewline(n), bare: true) for n in [1,2,3]

  lastChar = '-> lastChar;'
  doesNotThrow -> CoffeeScript.compile lastChar, bare: true

test "#1299: Disallow token misnesting", ->
  try
    CoffeeScript.compile '''
      [{
         ]}
    '''
    ok no
  catch e
    eq 'unmatched ]', e.message

test "#2981: Enforce initial indentation", ->
  try
    CoffeeScript.compile '  a\nb-'
    ok no
  catch e
    eq 'missing indentation', e.message

test "'single-line' expression containing multiple lines", ->
  doesNotThrow -> CoffeeScript.compile """
    (a, b) -> if a
      -a
    else if b
    then -b
    else null
  """

test "#1275: allow indentation before closing brackets", ->
  array = [
      1
      2
      3
    ]
  eq array, array
  do ->
  (
    a = 1
   )
  eq 1, a
1.9.3~dfsg/test/literate.litcoffee0000644000000000000000000000165112531364553015752 0ustar  rootrootLiterate CoffeeScript Test
--------------------------

comment comment

    test "basic literate CoffeeScript parsing", ->
      ok yes
      
now with a...
  
    test "broken up indentation", ->
    
... broken up ...

      do ->
      
... nested block.

        ok yes

Code must be separated from text by a blank line.

    test "code blocks must be preceded by a blank line", ->

The next line is part of the text and will not be executed.
      fail()

      ok yes        
        
Code in `backticks is not parsed` and...

    test "comments in indented blocks work", ->
      do ->
        do ->
          # Regular comment.
          
          ###
            Block comment.
          ###
          
          ok yes
          
Regular [Markdown](http://example.com/markdown) features, like links 
and unordered lists, are fine:

  * I 
  
  * Am
  
  * A
  
  * List

Tabs work too:

				test "tabbed code", ->
					ok yes
1.9.3~dfsg/test/classes.coffee0000644000000000000000000004062512531364553015071 0ustar  rootroot# Classes
# -------

# * Class Definition
# * Class Instantiation
# * Inheritance and Super

test "classes with a four-level inheritance chain", ->

  class Base
    func: (string) ->
      "zero/#{string}"

    @static: (string) ->
      "static/#{string}"

  class FirstChild extends Base
    func: (string) ->
      super('one/') + string

  SecondChild = class extends FirstChild
    func: (string) ->
      super('two/') + string

  thirdCtor = ->
    @array = [1, 2, 3]

  class ThirdChild extends SecondChild
    constructor: -> thirdCtor.call this

    # Gratuitous comment for testing.
    func: (string) ->
      super('three/') + string

  result = (new ThirdChild).func 'four'

  ok result is 'zero/one/two/three/four'
  ok Base.static('word') is 'static/word'

  FirstChild::func = (string) ->
    super('one/').length + string

  result = (new ThirdChild).func 'four'

  ok result is '9two/three/four'

  ok (new ThirdChild).array.join(' ') is '1 2 3'


test "constructors with inheritance and 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 "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 = ->
  Base::func = (string) ->
    'zero/' + string
  Base::['func-func'] = (string) ->
    "dynamic-#{string}"

  FirstChild = ->
  SecondChild = ->
  ThirdChild = ->
    @array = [1, 2, 3]
    this

  ThirdChild extends SecondChild extends FirstChild extends Base

  FirstChild::func = (string) ->
    super('one/') + string

  SecondChild::func = (string) ->
    super('two/') + string

  ThirdChild::func = (string) ->
    super('three/') + string

  result = (new ThirdChild).func 'four'

  ok result is 'zero/one/two/three/four'

  ok (new ThirdChild)['func-func']('thing') is 'dynamic-thing'


test "super with plain ol' prototypes", ->

  TopClass = ->
  TopClass::func = (arg) ->
    'top-' + arg

  SuperClass = ->
  SuperClass extends TopClass
  SuperClass::func = (arg) ->
    super 'super-' + arg

  SubClass = ->
  SubClass extends SuperClass
  SubClass::func = ->
    super 'sub'

  eq (new SubClass).func(), 'top-super-sub'


test "'@' referring to the current instance, and not being coerced into a call", ->

  class ClassName
    amI: ->
      @ instanceof ClassName

  obj = new ClassName
  ok obj.amI()


test "super() calls in constructors of classes that are defined as object properties", ->

  class Hive
    constructor: (name) -> @name = name

  class Hive.Bee extends Hive
    constructor: (name) -> super

  maya = new Hive.Bee 'Maya'
  ok maya.name is 'Maya'


test "classes with JS-keyword properties", ->

  class Class
    class: 'class'
    name: -> @class

  instance = new Class
  ok instance.class is 'class'
  ok instance.name() is 'class'


test "Classes with methods that are pre-bound to the instance, or statically, to the class", ->

  class Dog
    constructor: (name) ->
      @name = name

    bark: =>
      "#{@name} woofs!"

    @static = =>
      new this('Dog')

  spark = new Dog('Spark')
  fido  = new Dog('Fido')
  fido.bark = spark.bark

  ok fido.bark() is 'Spark woofs!'

  obj = func: Dog.static

  ok obj.func().name is 'Dog'


test "a bound function in a bound function", ->

  class Mini
    num: 10
    generate: =>
      for i in [1..3]
        =>
          @num

  m = new Mini
  eq (func() for func in m.generate()).join(' '), '10 10 10'


test "contructor called with varargs", ->

  class Connection
    constructor: (one, two, three) ->
      [@one, @two, @three] = [one, two, three]

    out: ->
      "#{@one}-#{@two}-#{@three}"

  list = [3, 2, 1]
  conn = new Connection list...
  ok conn instanceof Connection
  ok conn.out() is '3-2-1'


test "calling super and passing along all arguments", ->

  class Parent
    method: (args...) -> @args = args

  class Child extends Parent
    method: -> super

  c = new Child
  c.method 1, 2, 3, 4
  ok c.args.join(' ') is '1 2 3 4'


test "classes wrapped in decorators", ->

  func = (klass) ->
    klass::prop = 'value'
    klass

  func class Test
    prop2: 'value2'

  ok (new Test).prop  is 'value'
  ok (new Test).prop2 is 'value2'


test "anonymous classes", ->

  obj =
    klass: class
      method: -> 'value'

  instance = new obj.klass
  ok instance.method() is 'value'


test "Implicit objects as static properties", ->

  class Static
    @static =
      one: 1
      two: 2

  ok Static.static.one is 1
  ok Static.static.two is 2


test "nothing classes", ->

  c = class
  ok c instanceof Function


test "classes with static-level implicit objects", ->

  class A
    @static = one: 1
    two: 2

  class B
    @static = one: 1,
    two: 2

  eq A.static.one, 1
  eq A.static.two, undefined
  eq (new A).two, 2

  eq B.static.one, 1
  eq B.static.two, 2
  eq (new B).two, undefined


test "classes with value'd constructors", ->

  counter = 0
  classMaker = ->
    inner = ++counter
    ->
      @value = inner

  class One
    constructor: classMaker()

  class Two
    constructor: classMaker()

  eq (new One).value, 1
  eq (new Two).value, 2
  eq (new One).value, 1
  eq (new Two).value, 2


test "executable class bodies", ->

  class A
    if true
      b: 'b'
    else
      c: 'c'

  a = new A

  eq a.b, 'b'
  eq a.c, undefined


test "#2502: parenthesizing inner object values", ->

  class A
    category:  (type: 'string')
    sections:  (type: 'number', default: 0)

  eq (new A).category.type, 'string'

  eq (new A).sections.default, 0


test "conditional prototype property assignment", ->
  debug = false

  class Person
    if debug
      age: -> 10
    else
      age: -> 20

  eq (new Person).age(), 20


test "mild metaprogramming", ->

  class Base
    @attr: (name) ->
      @::[name] = (val) ->
        if arguments.length > 0
          @["_#{name}"] = val
        else
          @["_#{name}"]

  class Robot extends Base
    @attr 'power'
    @attr 'speed'

  robby = new Robot

  ok robby.power() is undefined

  robby.power 11
  robby.speed Infinity

  eq robby.power(), 11
  eq robby.speed(), Infinity


test "namespaced classes do not reserve their function name in outside scope", ->

  one = {}
  two = {}

  class one.Klass
    @label = "one"

  class two.Klass
    @label = "two"

  eq typeof Klass, 'undefined'
  eq one.Klass.label, 'one'
  eq two.Klass.label, 'two'


test "nested classes", ->

  class Outer
    constructor: ->
      @label = 'outer'

    class @Inner
      constructor: ->
        @label = 'inner'

  eq (new Outer).label, 'outer'
  eq (new Outer.Inner).label, 'inner'


test "variables in constructor bodies are correctly scoped", ->

  class A
    x = 1
    constructor: ->
      x = 10
      y = 20
    y = 2
    captured: ->
      {x, y}

  a = new A
  eq a.captured().x, 10
  eq a.captured().y, 2


test "Issue #924: Static methods in nested classes", ->

  class A
    @B: class
      @c = -> 5

  eq A.B.c(), 5


test "`class extends this`", ->

  class A
    func: -> 'A'

  B = null
  makeClass = ->
    B = class extends this
      func: -> super + ' B'

  makeClass.call A

  eq (new B()).func(), 'A B'


test "ensure that constructors invoked with splats return a new object", ->

  args = [1, 2, 3]
  Type = (@args) ->
  type = new Type args

  ok type and type instanceof Type
  ok type.args and type.args instanceof Array
  ok v is args[i] for v, i in type.args

  Type1 = (@a, @b, @c) ->
  type1 = new Type1 args...

  ok type1 instanceof   Type1
  eq type1.constructor, Type1
  ok type1.a is args[0] and type1.b is args[1] and type1.c is args[2]

  # Ensure that constructors invoked with splats cache the function.
  called = 0
  get = -> if called++ then false else class Type
  new get() args...

test "`new` shouldn't add extra parens", ->

  ok new Date().constructor is Date


test "`new` works against bare function", ->

  eq Date, new ->
    eq this, new => this
    Date


test "#1182: a subclass should be able to set its constructor to an external function", ->
  ctor = ->
    @val = 1
  class A
  class B extends A
    constructor: ctor
  eq (new B).val, 1

test "#1182: external constructors continued", ->
  ctor = ->
  class A
  class B extends A
    method: ->
    constructor: ctor
  ok B::method

test "#1313: misplaced __extends", ->
  nonce = {}
  class A
  class B extends A
    prop: nonce
    constructor: ->
  eq nonce, B::prop

test "#1182: execution order needs to be considered as well", ->
  counter = 0
  makeFn = (n) -> eq n, ++counter; ->
  class B extends (makeFn 1)
    @B: makeFn 2
    constructor: makeFn 3

test "#1182: external constructors with bound functions", ->
  fn = ->
    {one: 1}
    this
  class B
  class A
    constructor: fn
    method: => this instanceof A
  ok (new A).method.call(new B)

test "#1372: bound class methods with reserved names", ->
  class C
    delete: =>
  ok C::delete

test "#1380: `super` with reserved names", ->
  class C
    do: -> super
  ok C::do

  class B
    0: -> super
  ok B::[0]

test "#1464: bound class methods should keep context", ->
  nonce  = {}
  nonce2 = {}
  class C
    constructor: (@id) ->
    @boundStaticColon: => new this(nonce)
    @boundStaticEqual= => new this(nonce2)
  eq nonce,  C.boundStaticColon().id
  eq nonce2, C.boundStaticEqual().id

test "#1009: classes with reserved words as determined names", -> (->
  eq 'function', typeof (class @for)
  ok not /\beval\b/.test (class @eval).toString()
  ok not /\barguments\b/.test (class @arguments).toString()
).call {}

test "#1482: classes can extend expressions", ->
  id = (x) -> x
  nonce = {}
  class A then nonce: nonce
  class B extends id A
  eq nonce, (new B).nonce

test "#1598: super works for static methods too", ->

  class Parent
    method: ->
      'NO'
    @method: ->
      'yes'

  class Child extends Parent
    @method: ->
      'pass? ' + super

  eq Child.method(), 'pass? yes'

test "#1842: Regression with bound functions within bound class methods", ->

  class Store
    @bound: =>
      do =>
        eq this, Store

  Store.bound()

  # And a fancier case:

  class Store

    eq this, Store

    @bound: =>
      do =>
        eq this, Store

    @unbound: ->
      eq this, Store

    instance: =>
      ok this instanceof Store

  Store.bound()
  Store.unbound()
  (new Store).instance()

test "#1876: Class @A extends A", ->
  class A
  class @A extends A

  ok (new @A) instanceof A

test "#1813: Passing class definitions as expressions", ->
  ident = (x) -> x

  result = ident class A then x = 1

  eq result, A

  result = ident class B extends A
    x = 1

  eq result, B

test "#1966: external constructors should produce their return value", ->
  ctor = -> {}
  class A then constructor: ctor
  ok (new A) not instanceof A

test "#1980: regression with an inherited class with static function members", ->

  class A

  class B extends A
    @static: => 'value'

  eq B.static(), 'value'

test "#1534: class then 'use strict'", ->
  # [14.1 Directive Prologues and the Use Strict Directive](http://es5.github.com/#x14.1)
  nonce = {}
  error = 'do -> ok this'
  strictTest = "do ->'use strict';#{error}"
  return unless (try CoffeeScript.run strictTest, bare: yes catch e then nonce) is nonce

  throws -> CoffeeScript.run "class then 'use strict';#{error}", bare: yes
  doesNotThrow -> CoffeeScript.run "class then #{error}", bare: yes
  doesNotThrow -> CoffeeScript.run "class then #{error};'use strict'", bare: yes

  # comments are ignored in the Directive Prologue
  comments = ["""
  class
    ### comment ###
    'use strict'
    #{error}""",
  """
  class
    ### comment 1 ###
    ### comment 2 ###
    'use strict'
    #{error}""",
  """
  class
    ### comment 1 ###
    ### comment 2 ###
    'use strict'
    #{error}
    ### comment 3 ###"""
  ]
  throws (-> CoffeeScript.run comment, bare: yes) for comment in comments

  # [ES5 §14.1](http://es5.github.com/#x14.1) allows for other directives
  directives = ["""
  class
    'directive 1'
    'use strict'
    #{error}""",
  """
  class
    'use strict'
    'directive 2'
    #{error}""",
  """
  class
    ### comment 1 ###
    'directive 1'
    'use strict'
    #{error}""",
  """
  class
    ### comment 1 ###
    'directive 1'
    ### comment 2 ###
    'use strict'
    #{error}"""
  ]
  throws (-> CoffeeScript.run directive, bare: yes) for directive in directives

test "#2052: classes should work in strict mode", ->
  try
    do ->
      'use strict'
      class A
  catch e
    ok no

test "directives in class with extends ", ->
  strictTest = """
    class extends Object
      ### comment ###
      'use strict'
      do -> eq this, undefined
  """
  CoffeeScript.run strictTest, bare: yes

test "#2630: class bodies can't reference arguments", ->
  throws ->
    CoffeeScript.compile('class Test then arguments')

test "#2319: fn class n extends o.p [INDENT] x = 123", ->
  first = ->

  base = onebase: ->

  first class OneKeeper extends base.onebase
    one = 1
    one: -> one

  eq new OneKeeper().one(), 1


test "#2599: other typed constructors should be inherited", ->
  class Base
    constructor: -> return {}

  class Derived extends Base

  ok (new Derived) not instanceof Derived
  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'

  brokenArray = new BrokenArray
  ok brokenArray not instanceof BrokenArray
  ok typeof brokenArray.method is 'undefined'

  class WorkingArray extends Array
    constructor: -> super
    method: -> 'yes!'

  workingArray = new WorkingArray
  ok workingArray instanceof WorkingArray
  eq 'yes!', workingArray.method()


test "#2782: non-alphanumeric-named bound functions", ->
  class A
    'b:c': =>
      'd'

  eq (new A)['b:c'](), 'd'


test "#2781: overriding bound functions", ->
  class A
    a: ->
        @b()
    b: =>
        1

  class B extends A
    b: =>
        2

  b = (new A).b
  eq b(), 1

  b = (new B).b
  eq b(), 2


test "#2791: bound function with destructured argument", ->
  class Foo
    method: ({a}) => 'Bar'

  eq (new Foo).method({a: 'Bar'}), 'Bar'


test "#2796: ditto, ditto, ditto", ->
  answer = null

  outsideMethod = (func) ->
    func.call message: 'wrong!'

  class Base
    constructor: ->
      @message = 'right!'
      outsideMethod @echo

    echo: =>
      answer = @message

  new Base
  eq answer, 'right!'

test "#3063: Class bodies cannot contain pure statements", ->
  throws -> CoffeeScript.compile """
    class extends S
      return if S.f
      @f: => this
  """

test "#2949: super in static method with reserved name", ->
  class Foo
    @static: -> 'baz'

  class Bar extends Foo
    @static: -> super

  eq Bar.static(), 'baz'

test "#3232: super in static methods (not object-assigned)", ->
  class Foo
    @baz = -> true
    @qux = -> true

  class Bar extends Foo
    @baz = -> super
    Bar.qux = -> super

  ok Bar.baz()
  ok Bar.qux()

test "#1392 calling `super` in methods defined on namespaced classes", ->
  class Base
    m: -> 5
    n: -> 4
  namespace =
    A: ->
    B: ->
  namespace.A extends Base

  namespace.A::m = -> super
  eq 5, (new namespace.A).m()
  namespace.B::m = namespace.A::m
  namespace.A::m = null
  eq 5, (new namespace.B).m()

  count = 0
  getNamespace = -> count++; namespace
  getNamespace().A::n = -> super
  eq 4, (new namespace.A).n()
  eq 1, count

  class C
    @a: ->
    @a extends Base
    @a::m = -> super
  eq 5, (new C.a).m()

test "dynamic method names and super", ->
  class Base
    @m: -> 6
    m: -> 5
    m2: -> 4.5
    n: -> 4
  A = ->
  A extends Base

  m = 'm'
  A::[m] = -> super
  m = 'n'
  eq 5, (new A).m()

  name = -> count++; 'n'

  count = 0
  A::[name()] = -> super
  eq 4, (new A).n()
  eq 1, count

  m = 'm'
  m2 = 'm2'
  count = 0
  class B extends Base
    @[name()] = -> super
    @::[m] = -> super
    "#{m2}": -> super
  b = new B
  m = m2 = 'n'
  eq 6, B.m()
  eq 5, b.m()
  eq 4.5, b.m2()
  eq 1, count

  class C extends B
    m: -> super
  eq 5, (new C).m()
1.9.3~dfsg/test/importing.coffee0000644000000000000000000000231312531364553015434 0ustar  rootroot# Importing
# ---------

unless window? or testingBrowser?
  test "coffeescript modules can be imported and executed", ->

    magicKey = __filename
    magicValue = 0xFFFF

    if global[magicKey]?
      if exports?
        local = magicValue
        exports.method = -> local
    else
      global[magicKey] = {}
      if require?.extensions?
        ok require(__filename).method() is magicValue
      delete global[magicKey]

  test "javascript modules can be imported", ->
    magicVal = 1
    for module in 'import.js import2 .import2 import.extension.js import.unknownextension .coffee .coffee.md'.split ' '
      ok require("./importing/#{module}").value?() is magicVal, module

  test "coffeescript modules can be imported", ->
    magicVal = 2
    for module in '.import.coffee import.coffee import.extension.coffee'.split ' '
      ok require("./importing/#{module}").value?() is magicVal, module

  test "literate coffeescript modules can be imported", ->
    magicVal = 3
    # Leading space intentional to check for index.coffee.md
    for module in ' .import.coffee.md import.coffee.md import.litcoffee import.extension.coffee.md'.split ' '
      ok require("./importing/#{module}").value?() is magicVal, module
1.9.3~dfsg/test/control_flow.coffee0000644000000000000000000001763112531364553016144 0ustar  rootroot# Control Flow
# ------------

# * Conditionals
# * Loops
#   * For
#   * While
#   * Until
#   * Loop
# * Switch
# * Throw

# TODO: make sure postfix forms and expression coercion are properly tested

# shared identity function
id = (_) -> if arguments.length is 1 then _ else Array::slice.call(arguments)

# Conditionals

test "basic conditionals", ->
  if false
    ok false
  else if false
    ok false
  else
    ok true

  if true
    ok true
  else if true
    ok false
  else
    ok true

  unless true
    ok false
  else unless true
    ok false
  else
    ok true

  unless false
    ok true
  else unless false
    ok false
  else
    ok true

test "single-line conditional", ->
  if false then ok false else ok true
  unless false then ok true else ok false

test "nested conditionals", ->
  nonce = {}
  eq nonce, (if true
    unless false
      if false then false else
        if true
          nonce)

test "nested single-line conditionals", ->
  nonce = {}

  a = if false then undefined else b = if 0 then undefined else nonce
  eq nonce, a
  eq nonce, b

  c = if false then undefined else (if 0 then undefined else nonce)
  eq nonce, c

  d = if true then id(if false then undefined else nonce)
  eq nonce, d

test "empty conditional bodies", ->
  eq undefined, (if false
  else if false
  else)

test "conditional bodies containing only comments", ->
  eq undefined, (if true
    ###
    block comment
    ###
  else
    # comment
  )

  eq undefined, (if false
    # comment
  else if true
    ###
    block comment
    ###
  else)

test "return value of if-else is from the proper body", ->
  nonce = {}
  eq nonce, if false then undefined else nonce

test "return value of unless-else is from the proper body", ->
  nonce = {}
  eq nonce, unless true then undefined else nonce

test "assign inside the condition of a conditional statement", ->
  nonce = {}
  if a = nonce then 1
  eq nonce, a
  1 if b = nonce
  eq nonce, b


# Interactions With Functions

test "single-line function definition with single-line conditional", ->
  fn = -> if 1 < 0.5 then 1 else -1
  ok fn() is -1

test "function resturns conditional value with no `else`", ->
  fn = ->
    return if false then true
  eq undefined, fn()

test "function returns a conditional value", ->
  a = {}
  fnA = ->
    return if false then undefined else a
  eq a, fnA()

  b = {}
  fnB = ->
    return unless false then b else undefined
  eq b, fnB()

test "passing a conditional value to a function", ->
  nonce = {}
  eq nonce, id if false then undefined else nonce

test "unmatched `then` should catch implicit calls", ->
  a = 0
  trueFn = -> true
  if trueFn undefined then a++
  eq 1, a


# if-to-ternary

test "if-to-ternary with instanceof requires parentheses", ->
  nonce = {}
  eq nonce, (if {} instanceof Object
    nonce
  else
    undefined)

test "if-to-ternary as part of a larger operation requires parentheses", ->
  ok 2, 1 + if false then 0 else 1


# Odd Formatting

test "if-else indented within an assignment", ->
  nonce = {}
  result =
    if false
      undefined
    else
      nonce
  eq nonce, result

test "suppressed indentation via assignment", ->
  nonce = {}
  result =
    if      false then undefined
    else if no    then undefined
    else if 0     then undefined
    else if 1 < 0 then undefined
    else               id(
         if false then undefined
         else          nonce
    )
  eq nonce, result

test "tight formatting with leading `then`", ->
  nonce = {}
  eq nonce,
  if true
  then nonce
  else undefined

test "#738: inline function defintion", ->
  nonce = {}
  fn = if true then -> nonce
  eq nonce, fn()

test "#748: trailing reserved identifiers", ->
  nonce = {}
  obj = delete: true
  result = if obj.delete
    nonce
  eq nonce, result

# Postfix

test "#3056: multiple postfix conditionals", ->
  temp = 'initial'
  temp = 'ignored' unless true if false
  eq temp, 'initial'

# Loops

test "basic `while` loops", ->

  i = 5
  list = while i -= 1
    i * 2
  ok list.join(' ') is "8 6 4 2"

  i = 5
  list = (i * 3 while i -= 1)
  ok list.join(' ') is "12 9 6 3"

  i = 5
  func   = (num) -> i -= num
  assert = -> ok i < 5 > 0
  results = while func 1
    assert()
    i
  ok results.join(' ') is '4 3 2 1'

  i = 10
  results = while i -= 1 when i % 2 is 0
    i * 2
  ok results.join(' ') is '16 12 8 4'


test "Issue 759: `if` within `while` condition", ->

  2 while if 1 then 0


test "assignment inside the condition of a `while` loop", ->

  nonce = {}
  count = 1
  a = nonce while count--
  eq nonce, a
  count = 1
  while count--
    b = nonce
  eq nonce, b


test "While over break.", ->

  i = 0
  result = while i < 10
    i++
    break
  arrayEq result, []


test "While over continue.", ->

  i = 0
  result = while i < 10
    i++
    continue
  arrayEq result, []


test "Basic `until`", ->

  value = false
  i = 0
  results = until value
    value = true if i is 5
    i++
  ok i is 6


test "Basic `loop`", ->

  i = 5
  list = []
  loop
    i -= 1
    break if i is 0
    list.push i * 2
  ok list.join(' ') is '8 6 4 2'


test "break at the top level", ->
  for i in [1,2,3]
    result = i
    if i == 2
      break
  eq 2, result

test "break *not* at the top level", ->
  someFunc = ->
    i = 0
    while ++i < 3
      result = i
      break if i > 1
    result
  eq 2, someFunc()

# Switch

test "basic `switch`", ->

  num = 10
  result = switch num
    when 5 then false
    when 'a'
      true
      true
      false
    when 10 then true


    # Mid-switch comment with whitespace
    # and multi line
    when 11 then false
    else false

  ok result


  func = (num) ->
    switch num
      when 2, 4, 6
        true
      when 1, 3, 5
        false

  ok func(2)
  ok func(6)
  ok !func(3)
  eq func(8), undefined


test "Ensure that trailing switch elses don't get rewritten.", ->

  result = false
  switch "word"
    when "one thing"
      doSomething()
    else
      result = true unless false

  ok result

  result = false
  switch "word"
    when "one thing"
      doSomething()
    when "other thing"
      doSomething()
    else
      result = true unless false

  ok result


test "Should be able to handle switches sans-condition.", ->

  result = switch
    when null                     then 0
    when !1                       then 1
    when '' not of {''}           then 2
    when [] not instanceof Array  then 3
    when true is false            then 4
    when 'x' < 'y' > 'z'          then 5
    when 'a' in ['b', 'c']        then 6
    when 'd' in (['e', 'f'])      then 7
    else ok

  eq result, ok


test "Should be able to use `@properties` within the switch clause.", ->

  obj = {
    num: 101
    func: ->
      switch @num
        when 101 then '101!'
        else 'other'
  }

  ok obj.func() is '101!'


test "Should be able to use `@properties` within the switch cases.", ->

  obj = {
    num: 101
    func: (yesOrNo) ->
      result = switch yesOrNo
        when yes then @num
        else 'other'
      result
  }

  ok obj.func(yes) is 101


test "Switch with break as the return value of a loop.", ->

  i = 10
  results = while i > 0
    i--
    switch i % 2
      when 1 then i
      when 0 then break

  eq results.join(', '), '9, 7, 5, 3, 1'


test "Issue #997. Switch doesn't fallthrough.", ->

  val = 1
  switch true
    when true
      if false
        return 5
    else
      val = 2

  eq val, 1

# Throw

test "Throw should be usable as an expression.", ->
  try
    false or throw 'up'
    throw new Error 'failed'
  catch e
    ok e is 'up'


test "#2555, strange function if bodies", ->
  success = -> ok true
  failure = -> ok false

  success() if do ->
    yes

  failure() if try
    false

test "#1057: `catch` or `finally` in single-line functions", ->
  ok do -> try throw 'up' catch then yes
  ok do -> try yes finally 'nothing'

test "#2367: super in for-loop", ->
  class Foo
    sum: 0
    add: (val) -> @sum += val

  class Bar extends Foo
    add: (vals...) ->
      super val for val in vals
      @sum

  eq 10, (new Bar).add 2, 3, 5
1.9.3~dfsg/test/eval.coffee0000644000000000000000000000165312531364553014361 0ustar  rootrootif vm = require? 'vm'

  test "CoffeeScript.eval runs in the global context by default", ->
    global.punctuation = '!'
    code = '''
    global.fhqwhgads = "global superpower#{global.punctuation}"
    '''
    result = CoffeeScript.eval code
    eq result, 'global superpower!'
    eq fhqwhgads, 'global superpower!'

  test "CoffeeScript.eval can run in, and modify, a Script context sandbox", ->
    createContext = vm.Script.createContext ? vm.createContext
    sandbox = createContext()
    sandbox.foo = 'bar'
    code = '''
    global.foo = 'not bar!'
    '''
    result = CoffeeScript.eval code, {sandbox}
    eq result, 'not bar!'
    eq sandbox.foo, 'not bar!'

  test "CoffeeScript.eval can run in, but cannot modify, an ordinary object sandbox", ->
    sandbox = {foo: 'bar'}
    code = '''
    global.foo = 'not bar!'
    '''
    result = CoffeeScript.eval code, {sandbox}
    eq result, 'not bar!'
    eq sandbox.foo, 'bar'
1.9.3~dfsg/test/strict.coffee0000644000000000000000000001261612531364553014743 0ustar  rootroot# Strict Early Errors
# -------------------

# The following are prohibited under ES5's `strict` mode
# * `Octal Integer Literals`
# * `Octal Escape Sequences`
# * duplicate property definitions in `Object Literal`s
# * duplicate formal parameter
# * `delete` operand is a variable
# * `delete` operand is a parameter
# * `delete` operand is `undefined`
# * `Future Reserved Word`s as identifiers: implements, interface, let, package, private, protected, public, static, yield
# * `eval` or `arguments` as `catch` identifier
# * `eval` or `arguments` as formal parameter
# * `eval` or `arguments` as function declaration identifier
# * `eval` or `arguments` as LHS of assignment
# * `eval` or `arguments` as the operand of a post/pre-fix inc/dec-rement expression

# helper to assert that code complies with strict prohibitions
strict = (code, msg) ->
  throws (-> CoffeeScript.compile code), null, msg ? code
strictOk = (code, msg) ->
  doesNotThrow (-> CoffeeScript.compile code), msg ? code


test "octal integer literals prohibited", ->
  strict    '01'
  strict    '07777'
  # decimals with a leading '0' are also prohibited
  strict    '09'
  strict    '079'
  strictOk  '`01`'

test "octal escape sequences prohibited", ->
  strict    '"\\1"'
  strict    '"\\7"'
  strict    '"\\001"'
  strict    '"\\777"'
  strict    '"_\\1"'
  strict    '"\\1_"'
  strict    '"_\\1_"'
  strict    '"\\\\\\1"'
  strictOk  '"\\0"'
  eq "\x00", "\0"
  strictOk  '"\\08"'
  eq "\x008", "\08"
  strictOk  '"\\0\\8"'
  eq "\x008", "\0\8"
  strictOk  '"\\8"'
  eq "8", "\8"
  strictOk  '"\\\\1"'
  eq "\\" + "1", "\\1"
  strictOk  '"\\\\\\\\1"'
  eq "\\\\" + "1", "\\\\1"
  strictOk  "`'\\1'`"
  eq "\\" + "1", `"\\1"`

  # Also test other string types.
  strict           "'\\\\\\1'"
  eq "\x008",      '\08'
  eq "\\\\" + "1", '\\\\1'
  strict           "'''\\\\\\1'''"
  eq "\x008",      '''\08'''
  eq "\\\\" + "1", '''\\\\1'''
  strict           '"""\\\\\\1"""'
  eq "\x008",      """\08"""
  eq "\\\\" + "1", """\\\\1"""

test "duplicate formal parameters are prohibited", ->
  nonce = {}
  # a Param can be an Identifier, ThisProperty( @-param ), Array, or Object
  # a Param can also be a splat (...) or an assignment (param=value)
  # the following function expressions should throw errors
  strict '(_,_)->',          'param, param'
  strict '(_,_...)->',       'param, param...'
  strict '(_,_ = true)->',   'param, param='
  strict '(@_,@_)->',        'two @params'
  strict '(@case,@case)->',  'two @reserved'
  strict '(_,{_})->',        'param, {param}'
  strict '({_,_})->',        '{param, param}'
  strict '(_,[_])->',        'param, [param]'
  strict '([_,_])->',        '[param, param]'
  strict '(_,[_]=true)->',   'param, [param]='
  strict '(_,[@_,{_}])->',   'param, [@param, {param}]'
  strict '(_,[_,{@_}])->',   'param, [param, {@param}]'
  strict '(_,[_,{_}])->',    'param, [param, {param}]'
  strict '(_,[_,{__}])->',   'param, [param, {param2}]'
  strict '(_,[__,{_}])->',   'param, [param2, {param}]'
  strict '(__,[_,{_}])->',   'param, [param2, {param2}]'
  strict '(0:a,1:a)->',      '0:param,1:param'
  strict '({0:a,1:a})->',    '{0:param,1:param}'
  # the following function expressions should **not** throw errors
  strictOk '(_,@_)->'
  strictOk '(@_,_...)->'
  strictOk '(_,@_ = true)->'
  strictOk '(@_,{_})->'
  strictOk '({_,@_})->'
  strictOk '([_,@_])->'
  strictOk '({},_arg)->'
  strictOk '({},{})->'
  strictOk '([]...,_arg)->'
  strictOk '({}...,_arg)->'
  strictOk '({}...,[],_arg)->'
  strictOk '([]...,{},_arg)->'
  strictOk '(@case,_case)->'
  strictOk '(@case,_case...)->'
  strictOk '(@case...,_case)->'
  strictOk '(_case,@case)->'
  strictOk '(_case,@case...)->'
  strictOk '(a:a)->'
  strictOk '(a:a,a:b)->'

test "`delete` operand restrictions", ->
  strict 'a = 1; delete a'
  strictOk 'delete a' #noop
  strict '(a) -> delete a'
  strict '(a...) -> delete a'
  strict '(a = 1) -> delete a'
  strict '([a]) -> delete a'
  strict '({a}) -> delete a'

test "`Future Reserved Word`s, `eval` and `arguments` restrictions", ->

  access = (keyword, check = strict) ->
    check "#{keyword}.a = 1"
    check "#{keyword}[0] = 1"
  assign = (keyword, check = strict) ->
    check "#{keyword} = 1"
    check "#{keyword} += 1"
    check "#{keyword} -= 1"
    check "#{keyword} *= 1"
    check "#{keyword} /= 1"
    check "#{keyword} ?= 1"
    check "{keyword}++"
    check "++{keyword}"
    check "{keyword}--"
    check "--{keyword}"
  destruct = (keyword, check = strict) ->
    check "{#{keyword}}"
    check "o = {#{keyword}}"
  invoke = (keyword, check = strict) ->
    check "#{keyword} yes"
    check "do #{keyword}"
  fnDecl = (keyword, check = strict) ->
    check "class #{keyword}"
  param = (keyword, check = strict) ->
    check "(#{keyword}) ->"
    check "({#{keyword}}) ->"
  prop = (keyword, check = strict) ->
    check "a.#{keyword} = 1"
  tryCatch = (keyword, check = strict) ->
    check "try new Error catch #{keyword}"

  future = 'implements interface let package private protected public static'.split ' '
  for keyword in future
    access   keyword
    assign   keyword
    destruct keyword
    invoke   keyword
    fnDecl   keyword
    param    keyword
    prop     keyword, strictOk
    tryCatch keyword

  for keyword in ['eval', 'arguments']
    access   keyword, strictOk
    assign   keyword
    destruct keyword, strictOk
    invoke   keyword, strictOk
    fnDecl   keyword
    param    keyword
    prop     keyword, strictOk
    tryCatch keyword
1.9.3~dfsg/test/helpers.coffee0000644000000000000000000000603112531364553015067 0ustar  rootroot# Helpers
# -------

# pull the helpers from `CoffeeScript.helpers` into local variables
{starts, ends, repeat, compact, count, merge, extend, flatten, del, baseFileName} = CoffeeScript.helpers


# `starts`

test "the `starts` helper tests if a string starts with another string", ->
  ok     starts('01234', '012')
  ok not starts('01234', '123')

test "the `starts` helper can take an optional offset", ->
  ok     starts('01234', '34', 3)
  ok not starts('01234', '01', 1)


# `ends`

test "the `ends` helper tests if a string ends with another string", ->
  ok     ends('01234', '234')
  ok not ends('01234', '012')

test "the `ends` helper can take an optional offset", ->
  ok     ends('01234', '012', 2)
  ok not ends('01234', '234', 6)


# `repeat`

test "the `repeat` helper concatenates a given number of times", ->
  eq 'asdasdasd', repeat('asd', 3)

test "`repeat`ing a string 0 times always returns the empty string", ->
  eq '', repeat('whatever', 0)


# `compact`

test "the `compact` helper removes falsey values from an array, preserves truthy ones", ->
  allValues = [1, 0, false, obj={}, [], '', ' ', -1, null, undefined, true]
  truthyValues = [1, obj, [], ' ', -1, true]
  arrayEq truthyValues, compact(allValues)


# `count`

test "the `count` helper counts the number of occurrences of a string in another string", ->
  eq 1/0, count('abc', '')
  eq 0, count('abc', 'z')
  eq 1, count('abc', 'a')
  eq 1, count('abc', 'b')
  eq 2, count('abcdc', 'c')
  eq 2, count('abcdabcd','abc')


# `merge`

test "the `merge` helper makes a new object with all properties of the objects given as its arguments", ->
  ary = [0, 1, 2, 3, 4]
  obj = {}
  merged = merge obj, ary
  ok merged isnt obj
  ok merged isnt ary
  for own key, val of ary
    eq val, merged[key]


# `extend`

test "the `extend` helper performs a shallow copy", ->
  ary = [0, 1, 2, 3]
  obj = {}
  # should return the object being extended
  eq obj, extend(obj, ary)
  # should copy the other object's properties as well (obviously)
  eq 2, obj[2]


# `flatten`

test "the `flatten` helper flattens an array", ->
  success = yes
  (success and= typeof n is 'number') for n in flatten [0, [[[1]], 2], 3, [4]]
  ok success


# `del`

test "the `del` helper deletes a property from an object and returns the deleted value", ->
  obj = [0, 1, 2]
  eq 1, del(obj, 1)
  ok 1 not of obj


# `baseFileName`

test "the `baseFileName` helper returns the file name to write to", ->
  ext = '.js'
  sourceToCompiled =
    '.coffee': ext
    'a.coffee': 'a' + ext
    'b.coffee': 'b' + ext
    'coffee.coffee': 'coffee' + ext

    '.litcoffee': ext
    'a.litcoffee': 'a' + ext
    'b.litcoffee': 'b' + ext
    'coffee.litcoffee': 'coffee' + ext

    '.lit': ext
    'a.lit': 'a' + ext
    'b.lit': 'b' + ext
    'coffee.lit': 'coffee' + ext

    '.coffee.md': ext
    'a.coffee.md': 'a' + ext
    'b.coffee.md': 'b' + ext
    'coffee.coffee.md': 'coffee' + ext

  for sourceFileName, expectedFileName of sourceToCompiled
    name = baseFileName sourceFileName, yes
    filename = name + ext
    eq filename, expectedFileName
1.9.3~dfsg/test/slicing_and_splicing.coffee0000644000000000000000000000663012531364553017574 0ustar  rootroot# Slicing and Splicing
# --------------------

# * Slicing
# * Splicing

# shared array
shared = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# Slicing

test "basic slicing", ->
  arrayEq [7, 8, 9]   , shared[7..9]
  arrayEq [2, 3]      , shared[2...4]
  arrayEq [2, 3, 4, 5], shared[2...6]

test "slicing with variables as endpoints", ->
  [a, b] = [1, 4]
  arrayEq [1, 2, 3, 4], shared[a..b]
  arrayEq [1, 2, 3]   , shared[a...b]

test "slicing with expressions as endpoints", ->
  [a, b] = [1, 3]
  arrayEq [2, 3, 4, 5, 6], shared[(a+1)..2*b]
  arrayEq [2, 3, 4, 5]   , shared[a+1...(2*b)]

test "unbounded slicing", ->
  arrayEq [7, 8, 9]   , shared[7..]
  arrayEq [8, 9]      , shared[-2..]
  arrayEq [9]         , shared[-1...]
  arrayEq [0, 1, 2]   , shared[...3]
  arrayEq [0, 1, 2, 3], shared[..-7]

  arrayEq shared      , shared[..-1]
  arrayEq shared[0..8], shared[...-1]

  for a in [-shared.length..shared.length]
    arrayEq shared[a..] , shared[a...]
  for a in [-shared.length+1...shared.length]
    arrayEq shared[..a][...-1] , shared[...a]

  arrayEq [1, 2, 3], [1, 2, 3][..]

test "#930, #835, #831, #746 #624: inclusive slices to -1 should slice to end", ->
  arrayEq shared, shared[0..-1]
  arrayEq shared, shared[..-1]
  arrayEq shared.slice(1,shared.length), shared[1..-1]

test "string slicing", ->
  str = "abcdefghijklmnopqrstuvwxyz"
  ok str[1...1] is ""
  ok str[1..1] is "b"
  ok str[1...5] is "bcde"
  ok str[0..4] is "abcde"
  ok str[-5..] is "vwxyz"

test "#1722: operator precedence in unbounded slice compilation", ->
  list = [0..9]
  n = 2 # some truthy number in `list`
  arrayEq [0..n], list[..n]
  arrayEq [0..n], list[..n or 0]
  arrayEq [0..n], list[..if n then n else 0]

test "#2349: inclusive slicing to numeric strings", ->
  arrayEq [0, 1], [0..10][.."1"]


# Splicing

test "basic splicing", ->
  ary = [0..9]
  ary[5..9] = [0, 0, 0]
  arrayEq [0, 1, 2, 3, 4, 0, 0, 0], ary

  ary = [0..9]
  ary[2...8] = []
  arrayEq [0, 1, 8, 9], ary

test "unbounded splicing", ->
  ary = [0..9]
  ary[3..] = [9, 8, 7]
  arrayEq [0, 1, 2, 9, 8, 7]. ary

  ary[...3] = [7, 8, 9]
  arrayEq [7, 8, 9, 9, 8, 7], ary

  ary[..] = [1, 2, 3]
  arrayEq [1, 2, 3], ary

test "splicing with variables as endpoints", ->
  [a, b] = [1, 8]

  ary = [0..9]
  ary[a..b] = [2, 3]
  arrayEq [0, 2, 3, 9], ary

  ary = [0..9]
  ary[a...b] = [5]
  arrayEq [0, 5, 8, 9], ary

test "splicing with expressions as endpoints", ->
  [a, b] = [1, 3]

  ary = [0..9]
  ary[ a+1 .. 2*b+1 ] = [4]
  arrayEq [0, 1, 4, 8, 9], ary

  ary = [0..9]
  ary[a+1...2*b+1] = [4]
  arrayEq [0, 1, 4, 7, 8, 9], ary

test "splicing to the end, against a one-time function", ->
  ary = null
  fn = ->
    if ary
      throw 'err'
    else
      ary = [1, 2, 3]

  fn()[0..] = 1

  arrayEq ary, [1]

test "the return value of a splice literal should be the RHS", ->
  ary = [0, 0, 0]
  eq (ary[0..1] = 2), 2

  ary = [0, 0, 0]
  eq (ary[0..] = 3), 3

  arrayEq [ary[0..0] = 0], [0]

test "#1723: operator precedence in unbounded splice compilation", ->
  n = 4 # some truthy number in `list`

  list = [0..9]
  list[..n] = n
  arrayEq [n..9], list

  list = [0..9]
  list[..n or 0] = n
  arrayEq [n..9], list

  list = [0..9]
  list[..if n then n else 0] = n
  arrayEq [n..9], list

test "#2953: methods on endpoints in assignment from array splice literal", ->
  list = [0..9]

  Number.prototype.same = -> this
  list[1.same()...9.same()] = 5
  delete Number.prototype.same

  arrayEq [0, 5, 9], list
1.9.3~dfsg/test/function_invocation.coffee0000644000000000000000000003177412531364553017517 0ustar  rootroot# Function Invocation
# -------------------

# * Function Invocation
# * Splats in Function Invocations
# * Implicit Returns
# * Explicit Returns

# shared identity function
id = (_) -> if arguments.length is 1 then _ else [arguments...]

# helper to assert that a string should fail compilation
cantCompile = (code) ->
  throws -> CoffeeScript.compile code

test "basic argument passing", ->

  a = {}
  b = {}
  c = {}
  eq 1, (id 1)
  eq 2, (id 1, 2)[1]
  eq a, (id a)
  eq c, (id a, b, c)[2]


test "passing arguments on separate lines", ->

  a = {}
  b = {}
  c = {}
  ok(id(
    a
    b
    c
  )[1] is b)
  eq(0, id(
    0
    10
  )[0])
  eq(a,id(
    a
  ))
  eq b,
  (id b)


test "optional parens can be used in a nested fashion", ->

  call = (func) -> func()
  add = (a,b) -> a + b
  result = call ->
    inner = call ->
      add 5, 5
  ok result is 10


test "hanging commas and semicolons in argument list", ->

  fn = () -> arguments.length
  eq 2, fn(0,1,)
  eq 3, fn 0, 1,
  2
  eq 2, fn(0, 1;)
  # TODO: this test fails (the string compiles), but should it?
  #throws -> CoffeeScript.compile "fn(0,1,;)"
  throws -> CoffeeScript.compile "fn(0,1,;;)"
  throws -> CoffeeScript.compile "fn(0, 1;,)"
  throws -> CoffeeScript.compile "fn(,0)"
  throws -> CoffeeScript.compile "fn(;0)"


test "function invocation", ->

  func = ->
    return if true
  eq undefined, func()

  result = ("hello".slice) 3
  ok result is 'lo'


test "And even with strange things like this:", ->

  funcs  = [((x) -> x), ((x) -> x * x)]
  result = funcs[1] 5
  ok result is 25


test "More fun with optional parens.", ->

  fn = (arg) -> arg
  ok fn(fn {prop: 101}).prop is 101

  okFunc = (f) -> ok(f())
  okFunc -> true


test "chained function calls", ->
  nonce = {}
  identityWrap = (x) ->
    -> x
  eq nonce, identityWrap(identityWrap(nonce))()()
  eq nonce, (identityWrap identityWrap nonce)()()


test "Multi-blocks with optional parens.", ->

  fn = (arg) -> arg
  result = fn( ->
    fn ->
      "Wrapped"
  )
  ok result()() is 'Wrapped'


test "method calls", ->

  fnId = (fn) -> -> fn.apply this, arguments
  math = {
    add: (a, b) -> a + b
    anonymousAdd: (a, b) -> a + b
    fastAdd: fnId (a, b) -> a + b
  }
  ok math.add(5, 5) is 10
  ok math.anonymousAdd(10, 10) is 20
  ok math.fastAdd(20, 20) is 40


test "Ensure that functions can have a trailing comma in their argument list", ->

  mult = (x, mids..., y) ->
    x *= n for n in mids
    x *= y
  #ok mult(1, 2,) is 2
  #ok mult(1, 2, 3,) is 6
  ok mult(10, (i for i in [1..6])...) is 7200


test "`@` and `this` should both be able to invoke a method", ->
  nonce = {}
  fn          = (arg) -> eq nonce, arg
  fn.withAt   = -> @ nonce
  fn.withThis = -> this nonce
  fn.withAt()
  fn.withThis()


test "Trying an implicit object call with a trailing function.", ->

  a = null
  meth = (arg, obj, func) -> a = [obj.a, arg, func()].join ' '
  meth 'apple', b: 1, a: 13, ->
    'orange'
  ok a is '13 apple orange'


test "Ensure that empty functions don't return mistaken values.", ->

  obj =
    func: (@param, @rest...) ->
  ok obj.func(101, 102, 103, 104) is undefined
  ok obj.param is 101
  ok obj.rest.join(' ') is '102 103 104'


test "Passing multiple functions without paren-wrapping is legal, and should compile.", ->

  sum = (one, two) -> one() + two()
  result = sum ->
    7 + 9
  , ->
    1 + 3
  ok result is 20


test "Implicit call with a trailing if statement as a param.", ->

  func = -> arguments[1]
  result = func 'one', if false then 100 else 13
  ok result is 13


test "Test more function passing:", ->

  sum = (one, two) -> one() + two()

  result = sum( ->
    1 + 2
  , ->
    2 + 1
  )
  ok result is 6

  sum = (a, b) -> a + b
  result = sum(1
  , 2)
  ok result is 3


test "Chained blocks, with proper indentation levels:", ->

  counter =
    results: []
    tick: (func) ->
      @results.push func()
      this
  counter
    .tick ->
      3
    .tick ->
      2
    .tick ->
      1
  arrayEq [3,2,1], counter.results


test "This is a crazy one.", ->

  x = (obj, func) -> func obj
  ident = (x) -> x
  result = x {one: ident 1}, (obj) ->
    inner = ident(obj)
    ident inner
  ok result.one is 1


test "More paren compilation tests:", ->

  reverse = (obj) -> obj.reverse()
  ok reverse([1, 2].concat 3).join(' ') is '3 2 1'


test "Test for inline functions with parentheses and implicit calls.", ->

  combine = (func, num) -> func() * num
  result  = combine (-> 1 + 2), 3
  ok result is 9


test "Test for calls/parens/multiline-chains.", ->

  f = (x) -> x
  result = (f 1).toString()
    .length
  ok result is 1


test "Test implicit calls in functions in parens:", ->

  result = ((val) ->
    [].push val
    val
  )(10)
  ok result is 10


test "Ensure that chained calls with indented implicit object literals below are alright.", ->

  result = null
  obj =
    method: (val)  -> this
    second: (hash) -> result = hash.three
  obj
    .method(
      101
    ).second(
      one:
        two: 2
      three: 3
    )
  eq result, 3


test "Test newline-supressed call chains with nested functions.", ->

  obj  =
    call: -> this
  func = ->
    obj
      .call ->
        one two
      .call ->
        three four
    101
  eq func(), 101


test "Implicit objects with number arguments.", ->

  func = (x, y) -> y
  obj =
    prop: func "a", 1
  ok obj.prop is 1


test "Non-spaced unary and binary operators should cause a function call.", ->

  func = (val) -> val + 1
  ok (func +5) is 6
  ok (func -5) is -4


test "Prefix unary assignment operators are allowed in parenless calls.", ->

  func = (val) -> val + 1
  val = 5
  ok (func --val) is 5

test "#855: execution context for `func arr...` should be `null`", ->
  contextTest = -> eq @, if window? then window else global
  array = []
  contextTest array
  contextTest.apply null, array
  contextTest array...

test "#904: Destructuring function arguments with same-named variables in scope", ->
  a = b = nonce = {}
  fn = ([a,b]) -> {a:a,b:b}
  result = fn([c={},d={}])
  eq c, result.a
  eq d, result.b
  eq nonce, a
  eq nonce, b

test "Simple Destructuring function arguments with same-named variables in scope", ->
  x = 1
  f = ([x]) -> x
  eq f([2]), 2
  eq x, 1

test "caching base value", ->

  obj =
    index: 0
    0: {method: -> this is obj[0]}
  ok obj[obj.index++].method([]...)


test "passing splats to functions", ->
  arrayEq [0..4], id id [0..4]...
  fn = (a, b, c..., d) -> [a, b, c, d]
  range = [0..3]
  [first, second, others, last] = fn range..., 4, [5...8]...
  eq 0, first
  eq 1, second
  arrayEq [2..6], others
  eq 7, last

test "splat variables are local to the function", ->
  outer = "x"
  clobber = (avar, outer...) -> outer
  clobber "foo", "bar"
  eq "x", outer


test "Issue 894: Splatting against constructor-chained functions.", ->

  x = null
  class Foo
    bar: (y) -> x = y
  new Foo().bar([101]...)
  eq x, 101


test "Functions with splats being called with too few arguments.", ->

  pen = null
  method = (first, variable..., penultimate, ultimate) ->
    pen = penultimate
  method 1, 2, 3, 4, 5, 6, 7, 8, 9
  ok pen is 8
  method 1, 2, 3
  ok pen is 2
  method 1, 2
  ok pen is 2


test "splats with super() within classes.", ->

  class Parent
    meth: (args...) ->
      args
  class Child extends Parent
    meth: ->
      nums = [3, 2, 1]
      super nums...
  ok (new Child).meth().join(' ') is '3 2 1'


test "#1011: passing a splat to a method of a number", ->
  eq '1011', 11.toString [2]...
  eq '1011', (31).toString [3]...
  eq '1011', 69.0.toString [4]...
  eq '1011', (131.0).toString [5]...


test "splats and the `new` operator: functions that return `null` should construct their instance", ->
  args = []
  child = new (constructor = -> null) args...
  ok child instanceof constructor

test "splats and the `new` operator: functions that return functions should construct their return value", ->
  args = []
  fn = ->
  child = new (constructor = -> fn) args...
  ok child not instanceof constructor
  eq fn, child

test "implicit return", ->

  eq ok, new ->
    ok
    ### Should `return` implicitly   ###
    ### even with trailing comments. ###


test "implicit returns with multiple branches", ->
  nonce = {}
  fn = ->
    if false
      for a in b
        return c if d
    else
      nonce
  eq nonce, fn()


test "implicit returns with switches", ->
  nonce = {}
  fn = ->
    switch nonce
      when nonce then nonce
      else return undefined
  eq nonce, fn()


test "preserve context when generating closure wrappers for expression conversions", ->
  nonce = {}
  obj =
    property: nonce
    method: ->
      this.result = if false
        10
      else
        "a"
        "b"
        this.property
  eq nonce, obj.method()
  eq nonce, obj.property


test "don't wrap 'pure' statements in a closure", ->
  nonce = {}
  items = [0, 1, 2, 3, nonce, 4, 5]
  fn = (items) ->
    for item in items
      return item if item is nonce
  eq nonce, fn items


test "usage of `new` is careful about where the invocation parens end up", ->
  eq 'object', typeof new try Array
  eq 'object', typeof new do -> ->


test "implicit call against control structures", ->
  result = null
  save   = (obj) -> result = obj

  save switch id false
    when true
      'true'
    when false
      'false'

  eq result, 'false'

  save if id false
    'false'
  else
    'true'

  eq result, 'true'

  save unless id false
    'true'
  else
    'false'

  eq result, 'true'

  save try
    doesnt exist
  catch error
    'caught'

  eq result, 'caught'

  save try doesnt(exist) catch error then 'caught2'

  eq result, 'caught2'


test "#1420: things like `(fn() ->)`; there are no words for this one", ->
  fn = -> (f) -> f()
  nonce = {}
  eq nonce, (fn() -> nonce)

test "#1416: don't omit one 'new' when compiling 'new new'", ->
  nonce = {}
  obj = new new -> -> {prop: nonce}
  eq obj.prop, nonce

test "#1416: don't omit one 'new' when compiling 'new new fn()()'", ->
  nonce = {}
  argNonceA = {}
  argNonceB = {}
  fn = (a) -> (b) -> {a, b, prop: nonce}
  obj = new new fn(argNonceA)(argNonceB)
  eq obj.prop, nonce
  eq obj.a, argNonceA
  eq obj.b, argNonceB

test "#1840: accessing the `prototype` after function invocation should compile", ->
  doesNotThrow -> CoffeeScript.compile 'fn()::prop'

  nonce = {}
  class Test then id: nonce

  dotAccess = -> Test::
  protoAccess = -> Test

  eq dotAccess().id, nonce
  eq protoAccess()::id, nonce

test "#960: improved 'do'", ->

  do (nonExistent = 'one') ->
    eq nonExistent, 'one'

  overridden = 1
  do (overridden = 2) ->
    eq overridden, 2

  two = 2
  do (one = 1, two, three = 3) ->
    eq one, 1
    eq two, 2
    eq three, 3

  ret = do func = (two) ->
    eq two, 2
    func
  eq ret, func

test "#2617: implicit call before unrelated implicit object", ->
  pass = ->
    true

  result = if pass 1
    one: 1
  eq result.one, 1

test "#2292, b: f (z),(x)", ->
  f = (x, y) -> y
  one = 1
  two = 2
  o = b: f (one),(two)
  eq o.b, 2

test "#2297, Different behaviors on interpreting literal", ->
  foo = (x, y) -> y
  bar =
    baz: foo 100, on

  eq bar.baz, on

  qux = (x) -> x
  quux = qux
    corge: foo 100, true

  eq quux.corge, on

  xyzzy =
    e: 1
    f: foo
      a: 1
      b: 2
    ,
      one: 1
      two: 2
      three: 3
    g:
      a: 1
      b: 2
      c: foo 2,
        one: 1
        two: 2
        three: 3
      d: 3
    four: 4
    h: foo one: 1, two: 2, three: three: three: 3,
      2

  eq xyzzy.f.two, 2
  eq xyzzy.g.c.three, 3
  eq xyzzy.four, 4
  eq xyzzy.h, 2

test "#2715, Chained implicit calls", ->
  first  = (x)    -> x
  second = (x, y) -> y

  foo = first first
    one: 1
  eq foo.one, 1

  bar = first second
    one: 1, 2
  eq bar, 2

  baz = first second
    one: 1,
    2
  eq baz, 2

test "Implicit calls and new", ->
  first = (x) -> x
  foo = (@x) ->
  bar = first new foo first 1
  eq bar.x, 1

  third = (x, y, z) -> z
  baz = first new foo new foo third
        one: 1
        two: 2
        1
        three: 3
        2
  eq baz.x.x.three, 3

test "Loose tokens inside of explicit call lists", ->
  first = (x) -> x
  second = (x, y) -> y
  one = 1

  foo = second( one
                2)
  eq foo, 2

  bar = first( first
               one: 1)
  eq bar.one, 1

test "Non-callable literals shouldn't compile", ->
  cantCompile '1(2)'
  cantCompile '1 2'
  cantCompile '/t/(2)'
  cantCompile '/t/ 2'
  cantCompile '///t///(2)'
  cantCompile '///t/// 2'
  cantCompile "''(2)"
  cantCompile "'' 2"
  cantCompile '""(2)'
  cantCompile '"" 2'
  cantCompile '""""""(2)'
  cantCompile '"""""" 2'
  cantCompile '{}(2)'
  cantCompile '{} 2'
  cantCompile '[](2)'
  cantCompile '[] 2'
  cantCompile '[2..9] 2'
  cantCompile '[2..9](2)'
  cantCompile '[1..10][2..9] 2'
  cantCompile '[1..10][2..9](2)'

test 'implicit invocation with implicit object literal', ->
  f = (obj) -> eq 1, obj.a

  f
    a: 1
  obj =
    if f
      a: 2
    else
      a: 1
  eq 2, obj.a

  f
    "a": 1
  obj =
    if f
      "a": 2
    else
      "a": 1
  eq 2, obj.a

  # #3935: Implicit call when the first key of an implicit object has interpolation.
  a = 'a'
  f
    "#{a}": 1
  obj =
    if f
      "#{a}": 2
    else
      "#{a}": 1
  eq 2, obj.a
1.9.3~dfsg/test/strings.coffee0000644000000000000000000001706412531364553015126 0ustar  rootroot# String Literals
# ---------------

# TODO: refactor string literal tests
# TODO: add indexing and method invocation tests: "string"["toString"] is String::toString, "string".toString() is "string"

# * Strings
# * Heredocs

test "backslash escapes", ->
  eq "\\/\\\\", /\/\\/.source

eq '(((dollars)))', '\(\(\(dollars\)\)\)'
eq 'one two three', "one
 two
 three"
eq "four five", 'four

 five'

test "#3229, multiline strings", ->
  # Separate lines by default by a single space in literal strings.
  eq 'one
      two', 'one two'
  eq "one
      two", 'one two'
  eq '
        a
        b
    ', 'a b'
  eq "
        a
        b
    ", 'a b'
  eq 'one

        two', 'one two'
  eq "one

        two", 'one two'
  eq '
    indentation
      doesn\'t
  matter', 'indentation doesn\'t matter'
  eq 'trailing ws      
    doesn\'t matter', 'trailing ws doesn\'t matter'

  # Use backslashes at the end of a line to specify whitespace between lines.
  eq 'a \
      b\
      c  \
      d', 'a bc  d'
  eq "a \
      b\
      c  \
      d", 'a bc  d'
  eq 'ignore  \  
      trailing whitespace', 'ignore  trailing whitespace'

  # Backslash at the beginning of a literal string.
  eq '\
      ok', 'ok'
  eq '  \
      ok', '  ok'

  # #1273, empty strings.
  eq '\
     ', ''
  eq '
     ', ''
  eq '
          ', ''
  eq '   ', '   '

  # Same behavior in interpolated strings.
  eq "interpolation #{1}
      follows #{2}  \
      too #{3}\
      !", 'interpolation 1 follows 2  too 3!'
  eq "a #{
    'string ' + "inside
                 interpolation"
    }", "a string inside interpolation"
  eq "
      #{1}
     ", '1'

  # Handle escaped backslashes correctly.
  eq '\\', `'\\'`
  eq 'escaped backslash at EOL\\
      next line', 'escaped backslash at EOL\\ next line'
  eq '\\
      next line', '\\ next line'
  eq '\\
     ', '\\'
  eq '\\\\\\
     ', '\\\\\\'
  eq "#{1}\\
      after interpolation", '1\\ after interpolation'
  eq 'escaped backslash before slash\\  \
      next line', 'escaped backslash before slash\\  next line'
  eq 'triple backslash\\\
      next line', 'triple backslash\\next line'
  eq 'several escaped backslashes\\\\\\
      ok', 'several escaped backslashes\\\\\\ ok'
  eq 'several escaped backslashes slash\\\\\\\
      ok', 'several escaped backslashes slash\\\\\\ok'
  eq 'several escaped backslashes with trailing ws \\\\\\   
      ok', 'several escaped backslashes with trailing ws \\\\\\ ok'

  # Backslashes at beginning of lines.
  eq 'first line
      \   backslash at BOL', 'first line \   backslash at BOL'
  eq 'first line\
      \   backslash at BOL', 'first line\   backslash at BOL'

  # Backslashes at end of strings.
  eq 'first line \ ', 'first line  '
  eq 'first line
      second line \
      ', 'first line second line '
  eq 'first line
      second line
      \
      ', 'first line second line'
  eq 'first line
      second line

        \

      ', 'first line second line'

  # Edge case.
  eq 'lone

        \

        backslash', 'lone backslash'

test "#3249, escape newlines in heredocs with backslashes", ->
  # Ignore escaped newlines
  eq '''
    Set whitespace      \
       <- this is ignored\  
           none
      normal indentation
    ''', 'Set whitespace      <- this is ignorednone\n  normal indentation'
  eq """
    Set whitespace      \
       <- this is ignored\  
           none
      normal indentation
    """, 'Set whitespace      <- this is ignorednone\n  normal indentation'

  # Changed from #647, trailing backslash.
  eq '''
  Hello, World\

  ''', 'Hello, World'
  eq '''
    \\
  ''', '\\'

  # Backslash at the beginning of a literal string.
  eq '''\
      ok''', 'ok'
  eq '''  \
      ok''', '  ok'

  # Same behavior in interpolated strings.
  eq """
    interpolation #{1}
      follows #{2}  \
        too #{3}\
    !
  """, 'interpolation 1\n  follows 2  too 3!'
  eq """

    #{1} #{2}

    """, '\n1 2\n'

  # Handle escaped backslashes correctly.
  eq '''
    escaped backslash at EOL\\
      next line
  ''', 'escaped backslash at EOL\\\n  next line'
  eq '''\\

     ''', '\\\n'

  # Backslashes at beginning of lines.
  eq '''first line
      \   backslash at BOL''', 'first line\n\   backslash at BOL'
  eq """first line\
      \   backslash at BOL""", 'first line\   backslash at BOL'

  # Backslashes at end of strings.
  eq '''first line \ ''', 'first line  '
  eq '''
    first line
    second line \
  ''', 'first line\nsecond line '
  eq '''
    first line
    second line
    \
  ''', 'first line\nsecond line'
  eq '''
    first line
    second line

      \

  ''', 'first line\nsecond line\n'

  # Edge cases.
  eq '''lone

          \



        backslash''', 'lone\n\n  backslash'
  eq '''\
     ''', ''

test '#2388: `"""` in heredoc interpolations', ->
  eq """a heredoc #{
      "inside \
        interpolation"
    }""", "a heredoc inside interpolation"
  eq """a#{"""b"""}c""", 'abc'
  eq """#{""""""}""", ''

test "trailing whitespace", ->
  testTrailing = (str, expected) ->
    eq CoffeeScript.eval(str.replace /\|$/gm, ''), expected
  testTrailing '''"   |
      |
    a   |
           |
  "''', 'a'
  testTrailing """'''   |
      |
    a   |
           |
  '''""", '  \na   \n       '

#647
eq "''Hello, World\\''", '''
'\'Hello, World\\\''
'''
eq '""Hello, World\\""', """
"\"Hello, World\\\""
"""

test "#1273, escaping quotes at the end of heredocs.", ->
  # """\""" no longer compiles
  eq """\\""", '\\'
  eq """\\\"""", '\\\"'

a = """
    basic heredoc
    on two lines
    """
ok a is "basic heredoc\non two lines"

a = '''
    a
      "b
    c
    '''
ok a is "a\n  \"b\nc"

a = """
a
 b
  c
"""
ok a is "a\n b\n  c"

a = '''one-liner'''
ok a is 'one-liner'

a = """
      out
      here
"""
ok a is "out\nhere"

a = '''
       a
     b
   c
    '''
ok a is "    a\n  b\nc"

a = '''
a


b c
'''
ok a is "a\n\n\nb c"

a = '''more"than"one"quote'''
ok a is 'more"than"one"quote'

a = '''here's an apostrophe'''
ok a is "here's an apostrophe"

a = """""surrounded by two quotes"\""""
ok a is '""surrounded by two quotes""'

a = '''''surrounded by two apostrophes'\''''
ok a is "''surrounded by two apostrophes''"

# The indentation detector ignores blank lines without trailing whitespace
a = """
    one
    two

    """
ok a is "one\ntwo\n"

eq ''' line 0
  should not be relevant
    to the indent level
''', ' line 0\nshould not be relevant\n  to the indent level'

eq """
  interpolation #{
 "contents"
 }
  should not be relevant
    to the indent level
""", 'interpolation contents\nshould not be relevant\n  to the indent level'

eq ''' '\\\' ''', " '\\' "
eq """ "\\\" """, ' "\\" '

eq '''  <- keep these spaces ->  ''', '  <- keep these spaces ->  '

eq '''undefined''', 'undefined'
eq """undefined""", 'undefined'


test "#1046, empty string interpolations", ->
  eq "#{ }", ''

test "strings are not callable", ->
  throws -> CoffeeScript.compile '"a"()'
  throws -> CoffeeScript.compile '"a#{b}"()'
  throws -> CoffeeScript.compile '"a" 1'
  throws -> CoffeeScript.compile '"a#{b}" 1'
  throws -> CoffeeScript.compile '''
    "a"
       k: v
  '''
  throws -> CoffeeScript.compile '''
    "a#{b}"
       k: v
  '''

test "#3795: Escape otherwise invalid characters", ->
  eq '
', '\u2028'
  eq '
', '\u2029'
  eq '\0\
      1', '\x001'
  eq "
", '\u2028'
  eq "
", '\u2029'
  eq "\0\
      1", '\x001'
  eq '''
''', '\u2028'
  eq '''
''', '\u2029'
  eq '''\0\
      1''', '\x001'
  eq """
""", '\u2028'
  eq """
""", '\u2029'
  eq """\0\
      1""", '\x001'

  a = 'a'
  eq "#{a}
", 'a\u2028'
  eq "#{a}
", 'a\u2029'
  eq "#{a}\0\
      1", 'a\0' + '1'
  eq """#{a}
""", 'a\u2028'
  eq """#{a}
""", 'a\u2029'
  eq """#{a}\0\
      1""", 'a\0' + '1'
1.9.3~dfsg/test/importing/0000755000000000000000000000000012531364553014264 5ustar  rootroot1.9.3~dfsg/test/importing/index.coffee.md0000644000000000000000000000010412531364553017136 0ustar  rootrootRequired by ../importing.coffee

    module.exports = {value: -> 3}
1.9.3~dfsg/test/importing/.coffee.md0000644000000000000000000000012412531364553016110 0ustar  rootroot// Required by ../importing.coffee
module.exports = {value: function(){return 1;}};
1.9.3~dfsg/test/importing/.import20000644000000000000000000000012412531364553015656 0ustar  rootroot// Required by ../importing.coffee
module.exports = {value: function(){return 1;}};
1.9.3~dfsg/test/importing/import.coffee.md0000644000000000000000000000010412531364553017341 0ustar  rootrootRequired by ../importing.coffee

    module.exports = {value: -> 3}
1.9.3~dfsg/test/importing/import.extension.coffee0000644000000000000000000000010112531364553020752 0ustar  rootroot# Required by ../importing.coffee
module.exports = {value: -> 2}
1.9.3~dfsg/test/importing/.import.coffee.md0000644000000000000000000000010412531364553017417 0ustar  rootrootRequired by ../importing.coffee

    module.exports = {value: -> 3}
1.9.3~dfsg/test/importing/import.extension.coffee.md0000644000000000000000000000010412531364553021354 0ustar  rootrootRequired by ../importing.coffee

    module.exports = {value: -> 3}
1.9.3~dfsg/test/importing/.coffee0000644000000000000000000000012412531364553015511 0ustar  rootroot// Required by ../importing.coffee
module.exports = {value: function(){return 1;}};
1.9.3~dfsg/test/importing/import.coffee0000644000000000000000000000010112531364553016737 0ustar  rootroot# Required by ../importing.coffee
module.exports = {value: -> 2}
1.9.3~dfsg/test/importing/import.unknownextension0000644000000000000000000000012412531364553021151 0ustar  rootroot// Required by ../importing.coffee
module.exports = {value: function(){return 1;}};
1.9.3~dfsg/test/importing/import.litcoffee0000644000000000000000000000010412531364553017453 0ustar  rootrootRequired by ../importing.coffee

    module.exports = {value: -> 3}
1.9.3~dfsg/test/importing/.import.coffee0000644000000000000000000000010112531364553017015 0ustar  rootroot# Required by ../importing.coffee
module.exports = {value: -> 2}
1.9.3~dfsg/test/importing/import20000644000000000000000000000012412531364553015600 0ustar  rootroot// Required by ../importing.coffee
module.exports = {value: function(){return 1;}};
1.9.3~dfsg/test/importing/import.extension.js0000644000000000000000000000012412531364553020144 0ustar  rootroot// Required by ../importing.coffee
module.exports = {value: function(){return 1;}};
1.9.3~dfsg/test/importing/import.js0000644000000000000000000000012412531364553016131 0ustar  rootroot// Required by ../importing.coffee
module.exports = {value: function(){return 1;}};
1.9.3~dfsg/test/repl.coffee0000644000000000000000000000552712531364553014400 0ustar  rootrootreturn if global.testingBrowser

fs = require 'fs'

# REPL
# ----
Stream = require 'stream'

class MockInputStream extends Stream
  constructor: ->
    @readable = true

  resume: ->

  emitLine: (val) ->
    @emit 'data', new Buffer("#{val}\n")

class MockOutputStream extends Stream
  constructor: ->
    @writable = true
    @written = []

  write: (data) ->
    #console.log 'output write', arguments
    @written.push data

  lastWrite: (fromEnd = -1) ->
    @written[@written.length - 1 + fromEnd].replace /\n$/, ''

# Create a dummy history file
historyFile = '.coffee_history_test'
fs.writeFileSync historyFile, '1 + 2\n'

testRepl = (desc, fn) ->
  input = new MockInputStream
  output = new MockOutputStream
  repl = Repl.start {input, output, historyFile}
  test desc, -> fn input, output, repl

ctrlV = { ctrl: true, name: 'v'}


testRepl 'reads history file', (input, output, repl) ->
  input.emitLine repl.rli.history[0]
  eq '3', output.lastWrite()

testRepl "starts with coffee prompt", (input, output) ->
  eq 'coffee> ', output.lastWrite(0)

testRepl "writes eval to output", (input, output) ->
  input.emitLine '1+1'
  eq '2', output.lastWrite()

testRepl "comments are ignored", (input, output) ->
  input.emitLine '1 + 1 #foo'
  eq '2', output.lastWrite()

testRepl "output in inspect mode", (input, output) ->
  input.emitLine '"1 + 1\\n"'
  eq "'1 + 1\\n'", output.lastWrite()

testRepl "variables are saved", (input, output) ->
  input.emitLine "foo = 'foo'"
  input.emitLine 'foobar = "#{foo}bar"'
  eq "'foobar'", output.lastWrite()

testRepl "empty command evaluates to undefined", (input, output) ->
  input.emitLine ''
  eq 'undefined', output.lastWrite()

testRepl "ctrl-v toggles multiline prompt", (input, output) ->
  input.emit 'keypress', null, ctrlV
  eq '------> ', output.lastWrite(0)
  input.emit 'keypress', null, ctrlV
  eq 'coffee> ', output.lastWrite(0)

testRepl "multiline continuation changes prompt", (input, output) ->
  input.emit 'keypress', null, ctrlV
  input.emitLine ''
  eq '....... ', output.lastWrite(0)

testRepl "evaluates multiline", (input, output) ->
  # Stubs. Could assert on their use.
  output.cursorTo = (pos) ->
  output.clearLine = ->

  input.emit 'keypress', null, ctrlV
  input.emitLine 'do ->'
  input.emitLine '  1 + 1'
  input.emit 'keypress', null, ctrlV
  eq '2', output.lastWrite()

testRepl "variables in scope are preserved", (input, output) ->
  input.emitLine 'a = 1'
  input.emitLine 'do -> a = 2'
  input.emitLine 'a'
  eq '2', output.lastWrite()

testRepl "existential assignment of previously declared variable", (input, output) ->
  input.emitLine 'a = null'
  input.emitLine 'a ?= 42'
  eq '42', output.lastWrite()

testRepl "keeps running after runtime error", (input, output) ->
  input.emitLine 'a = b'
  input.emitLine 'a'
  eq 'undefined', output.lastWrite()

process.on 'exit', ->
  fs.unlinkSync historyFile
1.9.3~dfsg/test/soaks.coffee0000644000000000000000000000622012531364553014545 0ustar  rootroot# Soaks
# -----

# * Soaked Property Access
# * Soaked Method Invocation
# * Soaked Function Invocation


# Soaked Property Access

test "soaked property access", ->
  nonce = {}
  obj = a: b: nonce
  eq nonce    , obj?.a.b
  eq nonce    , obj?['a'].b
  eq nonce    , obj.a?.b
  eq nonce    , obj?.a?['b']
  eq undefined, obj?.a?.non?.existent?.property

test "soaked property access caches method calls", ->
  nonce ={}
  obj = fn: -> a: nonce
  eq nonce    , obj.fn()?.a
  eq undefined, obj.fn()?.b

test "soaked property access caching", ->
  nonce = {}
  counter = 0
  fn = ->
    counter++
    'self'
  obj =
    self: -> @
    prop: nonce
  eq nonce, obj[fn()]()[fn()]()[fn()]()?.prop
  eq 3, counter

test "method calls on soaked methods", ->
  nonce = {}
  obj = null
  eq undefined, obj?.a().b()
  obj = a: -> b: -> nonce
  eq nonce    , obj?.a().b()

test "postfix existential operator mixes well with soaked property accesses", ->
  eq false, nonexistent?.property?

test "function invocation with soaked property access", ->
  id = (_) -> _
  eq undefined, id nonexistent?.method()

test "if-to-ternary should safely parenthesize soaked property accesses", ->
  ok (if nonexistent?.property then false else true)

test "#726: don't check for a property on a conditionally-referenced nonexistent thing", ->
  eq undefined, nonexistent?[Date()]

test "#756: conditional assignment edge cases", ->
  # TODO: improve this test
  a = null
  ok isNaN      a?.b.c +  1
  eq undefined, a?.b.c += 1
  eq undefined, ++a?.b.c
  eq undefined, delete a?.b.c

test "operations on soaked properties", ->
  # TODO: improve this test
  a = b: {c: 0}
  eq 1,   a?.b.c +  1
  eq 1,   a?.b.c += 1
  eq 2,   ++a?.b.c
  eq yes, delete a?.b.c


# Soaked Method Invocation

test "soaked method invocation", ->
  nonce = {}
  counter = 0
  obj =
    self: -> @
    increment: -> counter++; @
  eq obj      , obj.self?()
  eq undefined, obj.method?()
  eq nonce    , obj.self?().property = nonce
  eq undefined, obj.method?().property = nonce
  eq obj      , obj.increment().increment().self?()
  eq 2        , counter

test "#733: conditional assignments", ->
  a = b: {c: null}
  eq a.b?.c?(), undefined
  a.b?.c or= (it) -> it
  eq a.b?.c?(1), 1
  eq a.b?.c?([2, 3]...), 2


# Soaked Function Invocation

test "soaked function invocation", ->
  nonce = {}
  id = (_) -> _
  eq nonce    , id?(nonce)
  eq nonce    , (id? nonce)
  eq undefined, nonexistent?(nonce)
  eq undefined, (nonexistent? nonce)

test "soaked function invocation with generated functions", ->
  nonce = {}
  id = (_) -> _
  maybe = (fn, arg) -> if typeof fn is 'function' then () -> fn(arg)
  eq maybe(id, nonce)?(), nonce
  eq (maybe id, nonce)?(), nonce
  eq (maybe false, nonce)?(), undefined

test "soaked constructor invocation", ->
  eq 42       , +new Number? 42
  eq undefined,  new Other?  42

test "soaked constructor invocations with caching and property access", ->
  semaphore = 0
  nonce = {}
  class C
    constructor: ->
      ok false if semaphore
      semaphore++
    prop: nonce
  eq nonce, (new C())?.prop
  eq 1, semaphore

test "soaked function invocation safe on non-functions", ->
  eq undefined, (0)?(1)
  eq undefined, (0)? 1, 2
1.9.3~dfsg/test/exception_handling.coffee0000644000000000000000000000506312531364553017273 0ustar  rootroot# Exception Handling
# ------------------

# shared nonce
nonce = {}


# Throw

test "basic exception throwing", ->
  throws (-> throw 'error'), 'error'


# Empty Try/Catch/Finally

test "try can exist alone", ->
  try

test "try/catch with empty try, empty catch", ->
  try
    # nothing
  catch err
    # nothing

test "single-line try/catch with empty try, empty catch", ->
  try catch err

test "try/finally with empty try, empty finally", ->
  try
    # nothing
  finally
    # nothing

test "single-line try/finally with empty try, empty finally", ->
  try finally

test "try/catch/finally with empty try, empty catch, empty finally", ->
  try
  catch err
  finally

test "single-line try/catch/finally with empty try, empty catch, empty finally", ->
  try catch err then finally


# Try/Catch/Finally as an Expression

test "return the result of try when no exception is thrown", ->
  result = try
    nonce
  catch err
    undefined
  finally
    undefined
  eq nonce, result

test "single-line result of try when no exception is thrown", ->
  result = try nonce catch err then undefined
  eq nonce, result

test "return the result of catch when an exception is thrown", ->
  fn = ->
    try
      throw ->
    catch err
      nonce
  doesNotThrow fn
  eq nonce, fn()

test "single-line result of catch when an exception is thrown", ->
  fn = ->
    try throw (->) catch err then nonce
  doesNotThrow fn
  eq nonce, fn()

test "optional catch", ->
  fn = ->
    try throw ->
    nonce
  doesNotThrow fn
  eq nonce, fn()


# Try/Catch/Finally Interaction With Other Constructs

test "try/catch with empty catch as last statement in a function body", ->
  fn = ->
    try nonce
    catch err
  eq nonce, fn()


# Catch leads to broken scoping: #1595

test "try/catch with a reused variable name.", ->
  do ->
    try
      inner = 5
    catch inner
      # nothing
  eq typeof inner, 'undefined'


# Allowed to destructure exceptions: #2580

test "try/catch with destructuring the exception object", ->

  result = try
    missing.object
  catch {message}
    message

  eq message, 'missing is not defined'



test "Try catch finally as implicit arguments", ->
  first = (x) -> x

  foo = no
  try
    first try iamwhoiam() finally foo = yes
  catch e
  eq foo, yes

  bar = no
  try
    first try iamwhoiam() catch e finally
    bar = yes
  catch e
  eq bar, yes

# Catch Should Not Require Param: #2900
test "parameter-less catch clause", ->
  try
    throw new Error 'failed'
  catch
    ok true

  try throw new Error 'failed' catch finally ok true

  ok try throw new Error 'failed' catch then true
1.9.3~dfsg/test/operators.coffee0000644000000000000000000002317212531364553015450 0ustar  rootroot# Operators
# ---------

# * Operators
# * Existential Operator (Binary)
# * Existential Operator (Unary)
# * Aliased Operators
# * [not] in/of
# * Chained Comparison

test "binary (2-ary) math operators do not require spaces", ->
  a = 1
  b = -1
  eq +1, a*-b
  eq -1, a*+b
  eq +1, a/-b
  eq -1, a/+b

test "operators should respect new lines as spaced", ->
  a = 123 +
  456
  eq 579, a

  b = "1#{2}3" +
  "456"
  eq '123456', b

test "multiple operators should space themselves", ->
  eq (+ +1), (- -1)

test "compound operators on successive lines", ->
  a = 1
  a +=
  1
  eq a, 2

test "bitwise operators", ->
  eq  2, (10 &   3)
  eq 11, (10 |   3)
  eq  9, (10 ^   3)
  eq 80, (10 <<  3)
  eq  1, (10 >>  3)
  eq  1, (10 >>> 3)
  num = 10; eq  2, (num &=   3)
  num = 10; eq 11, (num |=   3)
  num = 10; eq  9, (num ^=   3)
  num = 10; eq 80, (num <<=  3)
  num = 10; eq  1, (num >>=  3)
  num = 10; eq  1, (num >>>= 3)

test "`instanceof`", ->
  ok new String instanceof String
  ok new Boolean instanceof Boolean
  # `instanceof` supports negation by prefixing the operator with `not`
  ok new Number not instanceof String
  ok new Array not instanceof Boolean

test "use `::` operator on keywords `this` and `@`", ->
  nonce = {}
  obj =
    withAt:   -> @::prop
    withThis: -> this::prop
  obj.prototype = prop: nonce
  eq nonce, obj.withAt()
  eq nonce, obj.withThis()


# Existential Operator (Binary)

test "binary existential operator", ->
  nonce = {}

  b = a ? nonce
  eq nonce, b

  a = null
  b = undefined
  b = a ? nonce
  eq nonce, b

  a = false
  b = a ? nonce
  eq false, b

  a = 0
  b = a ? nonce
  eq 0, b

test "binary existential operator conditionally evaluates second operand", ->
  i = 1
  func = -> i -= 1
  result = func() ? func()
  eq result, 0

test "binary existential operator with negative number", ->
  a = null ? - 1
  eq -1, a


# Existential Operator (Unary)

test "postfix existential operator", ->
  ok (if nonexistent? then false else true)
  defined = true
  ok defined?
  defined = false
  ok defined?

test "postfix existential operator only evaluates its operand once", ->
  semaphore = 0
  fn = ->
    ok false if semaphore
    ++semaphore
  ok(if fn()? then true else false)

test "negated postfix existential operator", ->
  ok !nothing?.value

test "postfix existential operator on expressions", ->
  eq true, (1 or 0)?, true


# `is`,`isnt`,`==`,`!=`

test "`==` and `is` should be interchangeable", ->
  a = b = 1
  ok a is 1 and b == 1
  ok a == b
  ok a is b

test "`!=` and `isnt` should be interchangeable", ->
  a = 0
  b = 1
  ok a isnt 1 and b != 0
  ok a != b
  ok a isnt b


# [not] in/of

# - `in` should check if an array contains a value using `indexOf`
# - `of` should check if a property is defined on an object using `in`
test "in, of", ->
  arr = [1]
  ok 0 of arr
  ok 1 in arr
  # prefixing `not` to `in and `of` should negate them
  ok 1 not of arr
  ok 0 not in arr

test "`in` should be able to operate on an array literal", ->
  ok 2 in [0, 1, 2, 3]
  ok 4 not in [0, 1, 2, 3]
  arr = [0, 1, 2, 3]
  ok 2 in arr
  ok 4 not in arr
  # should cache the value used to test the array
  arr = [0]
  val = 0
  ok val++ in arr
  ok val++ not in arr
  val = 0
  ok val++ of arr
  ok val++ not of arr

test "`of` and `in` should be able to operate on instance variables", ->
  obj = {
    list: [2,3]
    in_list: (value) -> value in @list
    not_in_list: (value) -> value not in @list
    of_list: (value) -> value of @list
    not_of_list: (value) -> value not of @list
  }
  ok obj.in_list 3
  ok obj.not_in_list 1
  ok obj.of_list 0
  ok obj.not_of_list 2

test "#???: `in` with cache and `__indexOf` should work in argument lists", ->
  eq 1, [Object() in Array()].length

test "#737: `in` should have higher precedence than logical operators", ->
  eq 1, 1 in [1] and 1

test "#768: `in` should preserve evaluation order", ->
  share = 0
  a = -> share++ if share is 0
  b = -> share++ if share is 1
  c = -> share++ if share is 2
  ok a() not in [b(),c()]
  eq 3, share

test "#1099: empty array after `in` should compile to `false`", ->
  eq 1, [5 in []].length
  eq false, do -> return 0 in []

test "#1354: optimized `in` checks should not happen when splats are present", ->
  a = [6, 9]
  eq 9 in [3, a...], true

test "#1100: precedence in or-test compilation of `in`", ->
  ok 0 in [1 and 0]
  ok 0 in [1, 1 and 0]
  ok not (0 in [1, 0 or 1])

test "#1630: `in` should check `hasOwnProperty`", ->
  ok undefined not in length: 1

test "#1714: lexer bug with raw range `for` followed by `in`", ->
  0 for [1..2]
  ok not ('a' in ['b'])

  0 for [1..2]; ok not ('a' in ['b'])

  0 for [1..10] # comment ending
  ok not ('a' in ['b'])

test "#1099: statically determined `not in []` reporting incorrect result", ->
  ok 0 not in []

test "#1099: make sure expression tested gets evaluted when array is empty", ->
  a = 0
  (do -> a = 1) in []
  eq a, 1

# Chained Comparison

test "chainable operators", ->
  ok 100 > 10 > 1 > 0 > -1
  ok -1 < 0 < 1 < 10 < 100

test "`is` and `isnt` may be chained", ->
  ok true is not false is true is not false
  ok 0 is 0 isnt 1 is 1

test "different comparison operators (`>`,`<`,`is`,etc.) may be combined", ->
  ok 1 < 2 > 1
  ok 10 < 20 > 2+3 is 5

test "some chainable operators can be negated by `unless`", ->
  ok (true unless 0==10!=100)

test "operator precedence: `|` lower than `<`", ->
  eq 1, 1 | 2 < 3 < 4

test "preserve references", ->
  a = b = c = 1
  # `a == b <= c` should become `a === b && b <= c`
  # (this test does not seem to test for this)
  ok a == b <= c

test "chained operations should evaluate each value only once", ->
  a = 0
  ok 1 > a++ < 1

test "#891: incorrect inversion of chained comparisons", ->
  ok (true unless 0 > 1 > 2)
  ok (true unless (NaN = 0/0) < 0/0 < NaN)

test "#1234: Applying a splat to :: applies the splat to the wrong object", ->
  nonce = {}
  class C
    method: -> @nonce
    nonce: nonce

  arr = []
  eq nonce, C::method arr... # should be applied to `C::`

test "#1102: String literal prevents line continuation", ->
  eq "': '", '' +
     "': '"

test "#1703, ---x is invalid JS", ->
  x = 2
  eq (- --x), -1

test "Regression with implicit calls against an indented assignment", ->
  eq 1, a =
    1

  eq a, 1

test "#2155 ... conditional assignment to a closure", ->
  x = null
  func = -> x ?= (-> if true then 'hi')
  func()
  eq x(), 'hi'

test "#2197: Existential existential double trouble", ->
  counter = 0
  func = -> counter++
  func()? ? 100
  eq counter, 1

test "#2567: Optimization of negated existential produces correct result", ->
  a = 1
  ok !(!a?)
  ok !b?

test "#2508: Existential access of the prototype", ->
  eq NonExistent?::nothing, undefined
  ok Object?::toString

test "power operator", ->
  eq 27, 3 ** 3

test "power operator has higher precedence than other maths operators", ->
  eq 55, 1 + 3 ** 3 * 2
  eq -4, -2 ** 2
  eq false, !2 ** 2
  eq 0, (!2) ** 2
  eq -2, ~1 ** 5

test "power operator is right associative", ->
  eq 2, 2 ** 1 ** 3

test "power operator compound assignment", ->
  a = 2
  a **= 3
  eq 8, a

test "floor division operator", ->
  eq 2, 7 // 3
  eq -3, -7 // 3
  eq NaN, 0 // 0

test "floor division operator compound assignment", ->
  a = 7
  a //= 2
  eq 3, a

test "modulo operator", ->
  check = (a, b, expected) ->
    eq expected, a %% b, "expected #{a} %%%% #{b} to be #{expected}"
  check 0, 1, 0
  check 0, -1, -0
  check 1, 0, NaN
  check 1, 2, 1
  check 1, -2, -1
  check 1, 3, 1
  check 2, 3, 2
  check 3, 3, 0
  check 4, 3, 1
  check -1, 3, 2
  check -2, 3, 1
  check -3, 3, 0
  check -4, 3, 2
  check 5.5, 2.5, 0.5
  check -5.5, 2.5, 2.0

test "modulo operator compound assignment", ->
  a = -2
  a %%= 5
  eq 3, a

test "modulo operator converts arguments to numbers", ->
  eq 1, 1 %% '42'
  eq 1, '1' %% 42
  eq 1, '1' %% '42'

test "#3361: Modulo operator coerces right operand once", ->
  count = 0
  res = 42 %% valueOf: -> count += 1
  eq 1, count
  eq 0, res

test "#3363: Modulo operator coercing order", ->
  count = 2
  a = valueOf: -> count *= 2
  b = valueOf: -> count += 1
  eq 4, a %% b
  eq 5, count

test "#3598: Unary + and - coerce the operand once when it is an identifier", ->
  # Unary + and - do not generate `_ref`s when the operand is a number, for
  # readability. To make sure that they do when the operand is an identifier,
  # test that they are consistent with another unary operator as well as another
  # complex expression.
  # Tip: Making one of the tests temporarily fail lets you easily inspect the
  # compiled JavaScript.

  assertOneCoercion = (fn) ->
    count = 0
    value = valueOf: -> count++; 1
    fn value
    eq 1, count

  eq 1, 1 ? 0
  eq 1, +1 ? 0
  eq -1, -1 ? 0
  assertOneCoercion (a) ->
    eq 1, +a ? 0
  assertOneCoercion (a) ->
    eq -1, -a ? 0
  assertOneCoercion (a) ->
    eq -2, ~a ? 0
  assertOneCoercion (a) ->
    eq 0.5, a / 2 ? 0

  ok -2 <= 1 < 2
  ok -2 <= +1 < 2
  ok -2 <= -1 < 2
  assertOneCoercion (a) ->
    ok -2 <= +a < 2
  assertOneCoercion (a) ->
    ok -2 <= -a < 2
  assertOneCoercion (a) ->
    ok -2 <= ~a < 2
  assertOneCoercion (a) ->
    ok -2 <= a / 2 < 2

  arrayEq [0], (n for n in [0] by 1)
  arrayEq [0], (n for n in [0] by +1)
  arrayEq [0], (n for n in [0] by -1)
  assertOneCoercion (a) ->
    arrayEq [0], (n for n in [0] by +a)
  assertOneCoercion (a) ->
    arrayEq [0], (n for n in [0] by -a)
  assertOneCoercion (a) ->
    arrayEq [0], (n for n in [0] by ~a)
  assertOneCoercion (a) ->
    arrayEq [0], (n for n in [0] by a * 2 / 2)

  ok 1 in [0, 1]
  ok +1 in [0, 1]
  ok -1 in [0, -1]
  assertOneCoercion (a) ->
    ok +a in [0, 1]
  assertOneCoercion (a) ->
    ok -a in [0, -1]
  assertOneCoercion (a) ->
    ok ~a in [0, -2]
  assertOneCoercion (a) ->
    ok a / 2 in [0, 0.5]
1.9.3~dfsg/test/booleans.coffee0000644000000000000000000000103112531364553015222 0ustar  rootroot# Boolean Literals
# ----------------

# TODO: add method invocation tests: true.toString() is "true"

test "#764 Booleans should be indexable", ->
  toString = Boolean::toString

  eq toString, true['toString']
  eq toString, false['toString']
  eq toString, yes['toString']
  eq toString, no['toString']
  eq toString, on['toString']
  eq toString, off['toString']

  eq toString, true.toString
  eq toString, false.toString
  eq toString, yes.toString
  eq toString, no.toString
  eq toString, on.toString
  eq toString, off.toString
1.9.3~dfsg/CONTRIBUTING.md0000644000000000000000000000144512531364553013532 0ustar  rootroot## How to contribute to CoffeeScript

* Before you open a ticket or send a pull request, [search](https://github.com/jashkenas/coffeescript/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one.

* Before sending a pull request for a feature, be sure to have [tests](https://github.com/jashkenas/coffeescript/tree/master/test).

* Use the same coding style as the rest of the [codebase](https://github.com/jashkenas/coffeescript/tree/master/src). If you're just getting started with CoffeeScript, there's a nice [style guide](https://github.com/polarmobile/coffeescript-style-guide).

* In your pull request, do not add documentation to `index.html` or re-build the minified `coffee-script.js` file. We'll do those things before cutting a new release.1.9.3~dfsg/register.js0000644000000000000000000000005112531364553013453 0ustar  rootrootrequire('./lib/coffee-script/register');
1.9.3~dfsg/bin/0000755000000000000000000000000012531364553012045 5ustar  rootroot1.9.3~dfsg/bin/coffee0000755000000000000000000000030612531364553013221 0ustar  rootroot#!/usr/bin/env node

var path = require('path');
var fs   = require('fs');
var lib  = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');

require(lib + '/coffee-script/command').run();
1.9.3~dfsg/bin/cake0000755000000000000000000000030312531364553012672 0ustar  rootroot#!/usr/bin/env node

var path = require('path');
var fs   = require('fs');
var lib  = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');

require(lib + '/coffee-script/cake').run();
1.9.3~dfsg/repl.js0000644000000000000000000000006612531364553012577 0ustar  rootrootmodule.exports = require('./lib/coffee-script/repl');
1.9.3~dfsg/examples/0000755000000000000000000000000012531364553013113 5ustar  rootroot1.9.3~dfsg/examples/web_server.coffee0000644000000000000000000000042212531364553016425 0ustar  rootroot# Contributed by Jason Huggins

http = require 'http'

server = http.createServer (req, res) ->
  res.writeHeader 200, 'Content-Type': 'text/plain'
  res.write 'Hello, World!'
  res.end()

server.listen PORT = 3000

console.log "Server running at http://localhost:#{PORT}/"
1.9.3~dfsg/examples/custom_repl.coffee0000644000000000000000000000103612531364553016620 0ustar  rootroot###
Example of embedding the CoffeeScript REPL, strikingly similar to the Node REPL.
###

# Require 'coffee-script/repl' to import the repl module
repl = require '../repl'

console.log 'Custom REPL! Type `sayHi()` to see what it does!'

# Start the REPL with your configuration
r = repl.start
  prompt: 'my-repl> '

# Fields added to the context object are exposed as variables in the REPL
r.context.sayHi = -> console.log 'Hello'

# An exit event is emitted when the user exits the REPL
r.on 'exit', ->
  console.log 'Bye!'
  process.exit()
1.9.3~dfsg/examples/underscore.coffee0000644000000000000000000005104312531364553016440 0ustar  rootroot# **Underscore.coffee
# (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.**
# Underscore is freely distributable under the terms of the
# [MIT license](http://en.wikipedia.org/wiki/MIT_License).
# Portions of Underscore are inspired by or borrowed from
# [Prototype.js](http://prototypejs.org/api), Oliver Steele's
# [Functional](http://osteele.com), and John Resig's
# [Micro-Templating](http://ejohn.org).
# For all details and documentation:
# http://documentcloud.github.com/underscore/


# Baseline setup
# --------------

# Establish the root object, `window` in the browser, or `global` on the server.
root = this


# Save the previous value of the `_` variable.
previousUnderscore = root._


# Establish the object that gets thrown to break out of a loop iteration.
# `StopIteration` is SOP on Mozilla.
breaker = if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration


# Helper function to escape **RegExp** contents, because JS doesn't have one.
escapeRegExp = (string) -> string.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1')


# Save bytes in the minified (but not gzipped) version:
ArrayProto           = Array.prototype
ObjProto             = Object.prototype


# Create quick reference variables for speed access to core prototypes.
slice                = ArrayProto.slice
unshift              = ArrayProto.unshift
toString             = ObjProto.toString
hasOwnProperty       = ObjProto.hasOwnProperty
propertyIsEnumerable = ObjProto.propertyIsEnumerable


# All **ECMA5** native implementations we hope to use are declared here.
nativeForEach        = ArrayProto.forEach
nativeMap            = ArrayProto.map
nativeReduce         = ArrayProto.reduce
nativeReduceRight    = ArrayProto.reduceRight
nativeFilter         = ArrayProto.filter
nativeEvery          = ArrayProto.every
nativeSome           = ArrayProto.some
nativeIndexOf        = ArrayProto.indexOf
nativeLastIndexOf    = ArrayProto.lastIndexOf
nativeIsArray        = Array.isArray
nativeKeys           = Object.keys


# Create a safe reference to the Underscore object for use below.
_ = (obj) -> new wrapper(obj)


# Export the Underscore object for **CommonJS**.
if typeof(exports) != 'undefined' then exports._ = _


# Export Underscore to global scope.
root._ = _


# Current version.
_.VERSION = '1.1.0'


# Collection Functions
# --------------------

# The cornerstone, an **each** implementation.
# Handles objects implementing **forEach**, arrays, and raw objects.
_.each = (obj, iterator, context) ->
  try
    if nativeForEach and obj.forEach is nativeForEach
      obj.forEach iterator, context
    else if _.isNumber obj.length
      iterator.call context, obj[i], i, obj for i in [0...obj.length]
    else
      iterator.call context, val, key, obj  for own key, val of obj
  catch e
    throw e if e isnt breaker
  obj


# Return the results of applying the iterator to each element. Use JavaScript
# 1.6's version of **map**, if possible.
_.map = (obj, iterator, context) ->
  return obj.map(iterator, context) if nativeMap and obj.map is nativeMap
  results = []
  _.each obj, (value, index, list) ->
    results.push iterator.call context, value, index, list
  results


# **Reduce** builds up a single result from a list of values. Also known as
# **inject**, or **foldl**. Uses JavaScript 1.8's version of **reduce**, if possible.
_.reduce = (obj, iterator, memo, context) ->
  if nativeReduce and obj.reduce is nativeReduce
    iterator = _.bind iterator, context if context
    return obj.reduce iterator, memo
  _.each obj, (value, index, list) ->
    memo = iterator.call context, memo, value, index, list
  memo


# The right-associative version of **reduce**, also known as **foldr**. Uses
# JavaScript 1.8's version of **reduceRight**, if available.
_.reduceRight = (obj, iterator, memo, context) ->
  if nativeReduceRight and obj.reduceRight is nativeReduceRight
    iterator = _.bind iterator, context if context
    return obj.reduceRight iterator, memo
  reversed = _.clone(_.toArray(obj)).reverse()
  _.reduce reversed, iterator, memo, context


# Return the first value which passes a truth test.
_.detect = (obj, iterator, context) ->
  result = null
  _.each obj, (value, index, list) ->
    if iterator.call context, value, index, list
      result = value
      _.breakLoop()
  result


# Return all the elements that pass a truth test. Use JavaScript 1.6's
# **filter**, if it exists.
_.filter = (obj, iterator, context) ->
  return obj.filter iterator, context if nativeFilter and obj.filter is nativeFilter
  results = []
  _.each obj, (value, index, list) ->
    results.push value if iterator.call context, value, index, list
  results


# Return all the elements for which a truth test fails.
_.reject = (obj, iterator, context) ->
  results = []
  _.each obj, (value, index, list) ->
    results.push value if not iterator.call context, value, index, list
  results


# Determine whether all of the elements match a truth test. Delegate to
# JavaScript 1.6's **every**, if it is present.
_.every = (obj, iterator, context) ->
  iterator ||= _.identity
  return obj.every iterator, context if nativeEvery and obj.every is nativeEvery
  result = true
  _.each obj, (value, index, list) ->
    _.breakLoop() unless (result = result and iterator.call(context, value, index, list))
  result


# Determine if at least one element in the object matches a truth test. Use
# JavaScript 1.6's **some**, if it exists.
_.some = (obj, iterator, context) ->
  iterator ||= _.identity
  return obj.some iterator, context if nativeSome and obj.some is nativeSome
  result = false
  _.each obj, (value, index, list) ->
    _.breakLoop() if (result = iterator.call(context, value, index, list))
  result


# Determine if a given value is included in the array or object,
# based on `===`.
_.include = (obj, target) ->
  return _.indexOf(obj, target) isnt -1 if nativeIndexOf and obj.indexOf is nativeIndexOf
  return true for own key, val of obj when val is target
  false


# Invoke a method with arguments on every item in a collection.
_.invoke = (obj, method) ->
  args = _.rest arguments, 2
  (if method then val[method] else val).apply(val, args) for val in obj


# Convenience version of a common use case of **map**: fetching a property.
_.pluck = (obj, key) ->
  _.map(obj, (val) -> val[key])


# Return the maximum item or (item-based computation).
_.max = (obj, iterator, context) ->
  return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)
  result = computed: -Infinity
  _.each obj, (value, index, list) ->
    computed = if iterator then iterator.call(context, value, index, list) else value
    computed >= result.computed and (result = {value: value, computed: computed})
  result.value


# Return the minimum element (or element-based computation).
_.min = (obj, iterator, context) ->
  return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)
  result = computed: Infinity
  _.each obj, (value, index, list) ->
    computed = if iterator then iterator.call(context, value, index, list) else value
    computed < result.computed and (result = {value: value, computed: computed})
  result.value


# Sort the object's values by a criterion produced by an iterator.
_.sortBy = (obj, iterator, context) ->
  _.pluck(((_.map obj, (value, index, list) ->
    {value: value, criteria: iterator.call(context, value, index, list)}
  ).sort((left, right) ->
    a = left.criteria; b = right.criteria
    if a < b then -1 else if a > b then 1 else 0
  )), 'value')


# Use a comparator function to figure out at what index an object should
# be inserted so as to maintain order. Uses binary search.
_.sortedIndex = (array, obj, iterator) ->
  iterator ||= _.identity
  low =  0
  high = array.length
  while low < high
    mid = (low + high) >> 1
    if iterator(array[mid]) < iterator(obj) then low = mid + 1 else high = mid
  low


# Convert anything iterable into a real, live array.
_.toArray = (iterable) ->
  return []                   if (!iterable)
  return iterable.toArray()   if (iterable.toArray)
  return iterable             if (_.isArray(iterable))
  return slice.call(iterable) if (_.isArguments(iterable))
  _.values(iterable)


# Return the number of elements in an object.
_.size = (obj) -> _.toArray(obj).length


# Array Functions
# ---------------

# Get the first element of an array. Passing `n` will return the first N
# values in the array. Aliased as **head**. The `guard` check allows it to work
# with **map**.
_.first = (array, n, guard) ->
  if n and not guard then slice.call(array, 0, n) else array[0]


# Returns everything but the first entry of the array. Aliased as **tail**.
# Especially useful on the arguments object. Passing an `index` will return
# the rest of the values in the array from that index onward. The `guard`
# check allows it to work with **map**.
_.rest = (array, index, guard) ->
  slice.call(array, if _.isUndefined(index) or guard then 1 else index)


# Get the last element of an array.
_.last = (array) -> array[array.length - 1]


# Trim out all falsy values from an array.
_.compact = (array) -> item for item in array when item


# Return a completely flattened version of an array.
_.flatten = (array) ->
  _.reduce array, (memo, value) ->
    return memo.concat(_.flatten(value)) if _.isArray value
    memo.push value
    memo
  , []


# Return a version of the array that does not contain the specified value(s).
_.without = (array) ->
  values = _.rest arguments
  val for val in _.toArray(array) when not _.include values, val


# Produce a duplicate-free version of the array. If the array has already
# been sorted, you have the option of using a faster algorithm.
_.uniq = (array, isSorted) ->
  memo = []
  for el, i in _.toArray array
    memo.push el if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
  memo


# Produce an array that contains every item shared between all the
# passed-in arrays.
_.intersect = (array) ->
  rest = _.rest arguments
  _.select _.uniq(array), (item) ->
    _.all rest, (other) ->
      _.indexOf(other, item) >= 0


# Zip together multiple lists into a single array -- elements that share
# an index go together.
_.zip = ->
  length =  _.max _.pluck arguments, 'length'
  results = new Array length
  for i in [0...length]
    results[i] = _.pluck arguments, String i
  results


# If the browser doesn't supply us with **indexOf** (I'm looking at you, MSIE),
# we need this function. Return the position of the first occurrence of an
# item in an array, or -1 if the item is not included in the array.
_.indexOf = (array, item) ->
  return array.indexOf item if nativeIndexOf and array.indexOf is nativeIndexOf
  i = 0; l = array.length
  while l - i
    if array[i] is item then return i else i++
  -1


# Provide JavaScript 1.6's **lastIndexOf**, delegating to the native function,
# if possible.
_.lastIndexOf = (array, item) ->
  return array.lastIndexOf(item) if nativeLastIndexOf and array.lastIndexOf is nativeLastIndexOf
  i = array.length
  while i
    if array[i] is item then return i else i--
  -1


# Generate an integer Array containing an arithmetic progression. A port of
# [the native Python **range** function](http://docs.python.org/library/functions.html#range).
_.range = (start, stop, step) ->
  a         = arguments
  solo      = a.length <= 1
  i = start = if solo then 0 else a[0]
  stop      = if solo then a[0] else a[1]
  step      = a[2] or 1
  len       = Math.ceil((stop - start) / step)
  return []   if len <= 0
  range     = new Array len
  idx       = 0
  loop
    return range if (if step > 0 then i - stop else stop - i) >= 0
    range[idx] = i
    idx++
    i+= step


# Function Functions
# ------------------

# Create a function bound to a given object (assigning `this`, and arguments,
# optionally). Binding with arguments is also known as **curry**.
_.bind = (func, obj) ->
  args = _.rest arguments, 2
  -> func.apply obj or root, args.concat arguments


# Bind all of an object's methods to that object. Useful for ensuring that
# all callbacks defined on an object belong to it.
_.bindAll = (obj) ->
  funcs = if arguments.length > 1 then _.rest(arguments) else _.functions(obj)
  _.each funcs, (f) -> obj[f] = _.bind obj[f], obj
  obj


# Delays a function for the given number of milliseconds, and then calls
# it with the arguments supplied.
_.delay = (func, wait) ->
  args = _.rest arguments, 2
  setTimeout((-> func.apply(func, args)), wait)


# Memoize an expensive function by storing its results.
_.memoize = (func, hasher) ->
  memo = {}
  hasher or= _.identity
  ->
    key = hasher.apply this, arguments
    return memo[key] if key of memo
    memo[key] = func.apply this, arguments


# Defers a function, scheduling it to run after the current call stack has
# cleared.
_.defer = (func) ->
  _.delay.apply _, [func, 1].concat _.rest arguments


# Returns the first function passed as an argument to the second,
# allowing you to adjust arguments, run code before and after, and
# conditionally execute the original function.
_.wrap = (func, wrapper) ->
  -> wrapper.apply wrapper, [func].concat arguments


# Returns a function that is the composition of a list of functions, each
# consuming the return value of the function that follows.
_.compose = ->
  funcs = arguments
  ->
    args = arguments
    for i in [funcs.length - 1..0] by -1
      args = [funcs[i].apply(this, args)]
    args[0]


# Object Functions
# ----------------

# Retrieve the names of an object's properties.
_.keys = nativeKeys or (obj) ->
  return _.range 0, obj.length if _.isArray(obj)
  key for key, val of obj


# Retrieve the values of an object's properties.
_.values = (obj) ->
  _.map obj, _.identity


# Return a sorted list of the function names available in Underscore.
_.functions = (obj) ->
  _.filter(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()


# Extend a given object with all of the properties in a source object.
_.extend = (obj) ->
  for source in _.rest(arguments)
    obj[key] = val for key, val of source
  obj


# Create a (shallow-cloned) duplicate of an object.
_.clone = (obj) ->
  return obj.slice 0 if _.isArray obj
  _.extend {}, obj


# Invokes interceptor with the obj, and then returns obj.
# The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
_.tap = (obj, interceptor) ->
  interceptor obj
  obj


# Perform a deep comparison to check if two objects are equal.
_.isEqual = (a, b) ->
  # Check object identity.
  return true if a is b
  # Different types?
  atype = typeof(a); btype = typeof(b)
  return false if atype isnt btype
  # Basic equality test (watch out for coercions).
  return true if `a == b`
  # One is falsy and the other truthy.
  return false if (!a and b) or (a and !b)
  # One of them implements an `isEqual()`?
  return a.isEqual(b) if a.isEqual
  # Check dates' integer values.
  return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
  # Both are NaN?
  return false if _.isNaN(a) and _.isNaN(b)
  # Compare regular expressions.
  if _.isRegExp(a) and _.isRegExp(b)
    return a.source     is b.source and
           a.global     is b.global and
           a.ignoreCase is b.ignoreCase and
           a.multiline  is b.multiline
  # If a is not an object by this point, we can't handle it.
  return false if atype isnt 'object'
  # Check for different array lengths before comparing contents.
  return false if a.length and (a.length isnt b.length)
  # Nothing else worked, deep compare the contents.
  aKeys = _.keys(a); bKeys = _.keys(b)
  # Different object sizes?
  return false if aKeys.length isnt bKeys.length
  # Recursive comparison of contents.
  return false for key, val of a when !(key of b) or !_.isEqual(val, b[key])
  true


# Is a given array or object empty?
_.isEmpty = (obj) ->
  return obj.length is 0 if _.isArray(obj) or _.isString(obj)
  return false for own key of obj
  true


# Is a given value a DOM element?
_.isElement   = (obj) -> obj and obj.nodeType is 1


# Is a given value an array?
_.isArray     = nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift and not obj.callee)


# Is a given variable an arguments object?
_.isArguments = (obj) -> obj and obj.callee


# Is the given value a function?
_.isFunction  = (obj) -> !!(obj and obj.constructor and obj.call and obj.apply)


# Is the given value a string?
_.isString    = (obj) -> !!(obj is '' or (obj and obj.charCodeAt and obj.substr))


# Is a given value a number?
_.isNumber    = (obj) -> (obj is +obj) or toString.call(obj) is '[object Number]'


# Is a given value a boolean?
_.isBoolean   = (obj) -> obj is true or obj is false


# Is a given value a Date?
_.isDate      = (obj) -> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)


# Is the given value a regular expression?
_.isRegExp    = (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))


# Is the given value NaN -- this one is interesting. `NaN != NaN`, and
# `isNaN(undefined) == true`, so we make sure it's a number first.
_.isNaN       = (obj) -> _.isNumber(obj) and window.isNaN(obj)


# Is a given value equal to null?
_.isNull      = (obj) -> obj is null


# Is a given variable undefined?
_.isUndefined = (obj) -> typeof obj is 'undefined'


# Utility Functions
# -----------------

# Run Underscore.js in noConflict mode, returning the `_` variable to its
# previous owner. Returns a reference to the Underscore object.
_.noConflict = ->
  root._ = previousUnderscore
  this


# Keep the identity function around for default iterators.
_.identity = (value) -> value


# Run a function `n` times.
_.times = (n, iterator, context) ->
  iterator.call context, i for i in [0...n]


# Break out of the middle of an iteration.
_.breakLoop = -> throw breaker


# Add your own custom functions to the Underscore object, ensuring that
# they're correctly added to the OOP wrapper as well.
_.mixin = (obj) ->
  for name in _.functions(obj)
    addToWrapper name, _[name] = obj[name]


# Generate a unique integer id (unique within the entire client session).
# Useful for temporary DOM ids.
idCounter = 0
_.uniqueId = (prefix) ->
  (prefix or '') + idCounter++


# By default, Underscore uses **ERB**-style template delimiters, change the
# following template settings to use alternative delimiters.
_.templateSettings = {
  start:        '<%'
  end:          '%>'
  interpolate:  /<%=(.+?)%>/g
}


# JavaScript templating a-la **ERB**, pilfered from John Resig's
# *Secrets of the JavaScript Ninja*, page 83.
# Single-quote fix from Rick Strahl.
# With alterations for arbitrary delimiters, and to preserve whitespace.
_.template = (str, data) ->
  c = _.templateSettings
  endMatch = new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g")
  fn = new Function 'obj',
    'var p=[],print=function(){p.push.apply(p,arguments);};' +
    'with(obj||{}){p.push(\'' +
    str.replace(/\r/g, '\\r')
       .replace(/\n/g, '\\n')
       .replace(/\t/g, '\\t')
       .replace(endMatch,"✄")
       .split("'").join("\\'")
       .split("✄").join("'")
       .replace(c.interpolate, "',$1,'")
       .split(c.start).join("');")
       .split(c.end).join("p.push('") +
       "');}return p.join('');"
  if data then fn(data) else fn


# Aliases
# -------

_.forEach  = _.each
_.foldl    = _.inject = _.reduce
_.foldr    = _.reduceRight
_.select   = _.filter
_.all      = _.every
_.any      = _.some
_.contains = _.include
_.head     = _.first
_.tail     = _.rest
_.methods  = _.functions


# Setup the OOP Wrapper
# ---------------------

# If Underscore is called as a function, it returns a wrapped object that
# can be used OO-style. This wrapper holds altered versions of all the
# underscore functions. Wrapped objects may be chained.
wrapper = (obj) ->
  this._wrapped = obj
  this


# Helper function to continue chaining intermediate results.
result = (obj, chain) ->
  if chain then _(obj).chain() else obj


# A method to easily add functions to the OOP wrapper.
addToWrapper = (name, func) ->
  wrapper.prototype[name] = ->
    args = _.toArray arguments
    unshift.call args, this._wrapped
    result func.apply(_, args), this._chain


# Add all ofthe Underscore functions to the wrapper object.
_.mixin _


# Add all mutator Array functions to the wrapper.
_.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name) ->
  method = Array.prototype[name]
  wrapper.prototype[name] = ->
    method.apply(this._wrapped, arguments)
    result(this._wrapped, this._chain)


# Add all accessor Array functions to the wrapper.
_.each ['concat', 'join', 'slice'], (name) ->
  method = Array.prototype[name]
  wrapper.prototype[name] = ->
    result(method.apply(this._wrapped, arguments), this._chain)


# Start chaining a wrapped Underscore object.
wrapper::chain = ->
  this._chain = true
  this


# Extracts the result from a wrapped and chained object.
wrapper::value = -> this._wrapped
1.9.3~dfsg/examples/potion.coffee0000644000000000000000000000623612531364553015603 0ustar  rootroot# Examples from _why's Potion, the Readme and "Potion: A Short Pamphlet".

# 5 times: "Odelay!" print.

print "Odelay!" for i in [1..5]


# add = (x, y): x + y.
# add(2, 4) string print

add = (x, y) -> x + y
print add 2, 4


# loop: 'quaff' print.

loop print 'quaff'


# ('cheese', 'bread', 'mayo') at (1) print

print ['cheese', 'bread', 'mayo'][1]


# (language='Potion', pointless=true) at (key='language') print

print {language: 'Potion', pointless: true}['language']


# minus = (x, y): x - y.
# minus (y=10, x=6)

minus = (x, y) -> x - y
minus 6, 10


# foods = ('cheese', 'bread', 'mayo')
# foods (2)

foods = ['cheese', 'bread', 'mayo']
foods[2]


# (dog='canine', cat='feline', fox='vulpine') each (key, val):
#   (key, ' is a ', val) join print.

for key, val of {dog: 'canine', cat: 'feline', fox: 'vulpine'}
  print "#{key} is a #{val}"


# Person = class: /name, /age, /sex.
# Person print = ():
#   ('My name is ', /name, '.') join print.

class Person
  print: ->
    print "My name is #{@name}."


# p = Person ()
# p /name string print

p = new Person
print p.name


# Policeman = Person class (rank): /rank = rank.
# Policeman print = ():
#   ('My name is ', /name, ' and I'm a ', /rank, '.') join print.
#
# Policeman ('Constable') print

class Policeman extends Person
  (@rank) ->

  print: ->
    print "My name is #{@name} and I'm a #{@rank}."

print new Policeman 'Constable'


# app = [window (width=200, height=400)
#         [para 'Welcome.', button 'OK']]
# app first name

app =
  window:
    width: 200
    height: 200
  para:    'Welcome.'
  button:  'OK'

app.window


# x = 1
# y = 2
#
# x = 1, y = 2

x = 1
y = 2

x = 1; y = 2


# table = (language='Potion'
#           pointless=true)

table =
  language: 'Potion'
  pointless: yes


# # this foul business...
# String length = (): 10.

# this foul business...
String::length = -> 10


# block = :
#   'potion' print.

block = ->
  print 'potion'


# if (age > 100): 'ancient'.

if age > 100 then 'ancient'


# author =
#   if (title == 'Jonathan Strange & Mr. Norrell'):
#     'Susanna Clarke'.
#   elsif (title == 'The Star Diaries'):
#     'Stanislaw Lem'.
#   elsif (title == 'The Slynx'):
#     'Tatyana Tolstaya'.
#   else:
#     '... probably Philip K. Dick'.

switch author
  when 'Jonathan Strange & Mr. Norrell'
    'Susanna Clarke'
  when 'The Star Diaries'
    'Stanislaw Lem'
  when 'The Slynx'
    'Tatyana Tolstaya'
  else
    '... probably Philip K. Dick'


# count = 8
# while (count > 0):
#   'quaff' print
#   count--.

count = 8
while count > 0
  print 'quaff'
  count--


# 1 to 5 (a):
#   a string print.

print a for a in [1..5]


# if (3 ?gender):
#   "Huh? Numbers are sexed? That's amazing." print.

if 3.gender?
  print "Huh? Numbers are sexed? That's amazing."


# HomePage get = (url):
#   session = url query ? at ('session').

HomePage::get = (url) ->
  session = url.query?.session


# BTree = class: /left, /right.
# b = BTree ()
# b /left = BTree ()
# b /right = BTree ()

BTree   = ->
b       = new BTree
b.left  = new BTree
b.right = new BTree


# BTree = class: /left, /right.
# b = BTree ()
#
# if (b ? /left):
#   'left path found!' print.

BTree = ->
b = new BTree

print 'left path found!' if b.left?
1.9.3~dfsg/examples/beautiful_code/0000755000000000000000000000000012531364553016065 5ustar  rootroot1.9.3~dfsg/examples/beautiful_code/regular_expression_matcher.coffee0000644000000000000000000000230412531364553024660 0ustar  rootroot# Beautiful Code, Chapter 1.
# Implements a regular expression matcher that supports character matches,
# '.', '^', '$', and '*'.

# Search for the regexp anywhere in the text.
match = (regexp, text) ->
  return match_here(regexp.slice(1), text) if regexp[0] is '^'
  while text
    return true if match_here(regexp, text)
    text = text.slice(1)
  false

# Search for the regexp at the beginning of the text.
match_here = (regexp, text) ->
  [cur, next] = [regexp[0], regexp[1]]
  if regexp.length is 0 then return true
  if next is '*' then return match_star(cur, regexp.slice(2), text)
  if cur is '$' and not next then return text.length is 0
  if text and (cur is '.' or cur is text[0]) then return match_here(regexp.slice(1), text.slice(1))
  false

# Search for a kleene star match at the beginning of the text.
match_star = (c, regexp, text) ->
  loop
    return true if match_here(regexp, text)
    return false unless text and (text[0] is c or c is '.')
    text = text.slice(1)

console.log match("ex", "some text")
console.log match("s..t", "spit")
console.log match("^..t", "buttercup")
console.log match("i..$", "cherries")
console.log match("o*m", "vrooooommm!")
console.log match("^hel*o$", "hellllllo")1.9.3~dfsg/examples/beautiful_code/quicksort_runtime.coffee0000644000000000000000000000050712531364553023027 0ustar  rootroot# Beautiful Code, Chapter 3.
# Produces the expected runtime of Quicksort, for every integer from 1 to N.

runtime = (N) ->
  [sum, t] = [0, 0]
  for n in [1..N]
    sum += 2 * t
    t = n - 1 + sum / n
  t

console.log runtime(3) is 2.6666666666666665
console.log runtime(5) is 7.4
console.log runtime(8) is 16.92142857142857
1.9.3~dfsg/examples/beautiful_code/binary_search.coffee0000644000000000000000000000101312531364553022042 0ustar  rootroot# Beautiful Code, Chapter 6.
# The implementation of binary search that is tested.

# Return the index of an element in a sorted list. (or -1, if not present)
index = (list, target) ->
  [low, high] = [0, list.length]
  while low < high
    mid = (low + high) >> 1
    val = list[mid]
    return mid if val is target
    if val < target then low = mid + 1 else high = mid
  return -1

console.log 2 is index [10, 20, 30, 40, 50], 30
console.log 4 is index [-97, 35, 67, 88, 1200], 1200
console.log 0 is index [0, 45, 70], 01.9.3~dfsg/examples/blocks.coffee0000644000000000000000000000205412531364553015542 0ustar  rootroot# After wycats' http://yehudakatz.com/2010/02/07/the-building-blocks-of-ruby/

# Sinatra.
get '/hello', ->
  'Hello World'


# Append.
append = (location, data) ->
  path = new Pathname location
  throw new Error "Location does not exist" unless fs.existsSync(location)

  File.open path, 'a', (file) ->
    file.console.log YAML.dump data

  data


# Rubinius' File.open implementation.
File.open = (path, mode, block) ->
  io = new File path, mode

  return io unless block

  try
    block io
  finally
    io.close() unless io.closed()


# Write.
write = (location, data) ->
  path = new Pathname location
  throw new Error "Location does not exist" unless fs.existsSync location

  File.open path, 'w', (file) ->
    return false if Digest.MD5.hexdigest(file.read()) is data.hash()
    file.console.log YAML.dump data
    true


# Rails' respond_to.
index = ->
  people = Person.find 'all'

  respond_to (format) ->
    format.html()
    format.xml -> render xml: people.xml()


# Synchronization.
synchronize = (block) ->
  lock()
  try block() finally unlock()
1.9.3~dfsg/examples/poignant.coffee0000644000000000000000000001113112531364553016100 0ustar  rootroot# Examples from the Poignant Guide.
# These are examples of syntax differences between CoffeeScript and Ruby,
# they won't run.

# ['toast', 'cheese', 'wine'].each { |food| print food.capitalize }

print food.capitalize() for food in ['toast', 'wine', 'cheese']




# class LotteryTicket
#   def picks;           @picks;            end
#   def picks=(var);     @picks = var;      end
#   def purchased;       @purchased;        end
#   def purchased=(var); @purchased = var;  end
# end

LotteryTicket =
  get_picks:     -> @picks
  set_picks:     (@picks) ->
  get_purchased: -> @purchase
  set_purchased: (@purchased) ->



# class << LotteryDraw
#   def play
#     result = LotteryTicket.new_random
#     winners = {}
#     @@tickets.each do |buyer, ticket_list|
#       ticket_list.each do |ticket|
#         score = ticket.score( result )
#         next if score.zero?
#         winners[buyer] ||= []
#         winners[buyer] << [ ticket, score ]
#       end
#     end
#     @@tickets.clear
#     winners
#   end
# end

LotteryDraw =
  play: ->
    result  = LotteryTicket.new_random()
    winners = {}
    for buyer, ticketList of @tickets
      for ticket in ticketList when (score = ticket.score result) isnt 0
        (winners[buyer] or= []).push [ticket, score]
    @tickets = {}
    winners



# module WishScanner
#   def scan_for_a_wish
#     wish = self.read.detect do |thought|
#       thought.index( 'wish: ' ) == 0
#     end
#     wish.gsub( 'wish: ', '' )
#   end
# end

WishScanner =
  scan_for_a_wish: ->
    wish = @read().detect (thought) -> thought.indexOf('wish: ') is 0
    wish.replace 'wish: ', ''



# class Creature
#
#   # This method applies a hit taken during a fight.
#   def hit( damage )
#     p_up = rand( charisma )
#     if p_up % 9 == 7
#       @life += p_up / 4
#       console.log "[#{ self.class } magick powers up #{ p_up }!]"
#     end
#     @life -= damage
#     console.log "[#{ self.class } has died.]" if @life <= 0
#   end
#
#   # This method takes one turn in a fight.
#   def fight( enemy, weapon )
#     if life <= 0
#       console.log "[#{ self.class } is too dead to fight!]"
#       return
#     end
#
#     # Attack the opponent
#     your_hit = rand( strength + weapon )
#     console.log "[You hit with #{ your_hit } points of damage!]"
#     enemy.hit( your_hit )
#
#     # Retaliation
#     p enemy
#     if enemy.life > 0
#       enemy_hit = rand( enemy.strength + enemy.weapon )
#       console.log "[Your enemy hit with #{ enemy_hit } points of damage!]"
#       self.hit( enemy_hit )
#     end
#   end
#
# end

Creature =

  # This method applies a hit taken during a fight.
  hit: (damage) ->
    p_up = Math.rand @charisma
    if p_up % 9 is 7
      @life += p_up / 4
      console.log "[#{@name} magick powers up #{p_up}!]"
    @life -= damage
    if @life <= 0 then console.log "[#{@name} has died.]"

  # This method takes one turn in a fight.
  fight: (enemy, weapon) ->
    return console.log "[#{@name} is too dead to fight!]" if @life <= 0

    # Attack the opponent.
    your_hit = Math.rand @strength + weapon
    console.log "[You hit with #{your_hit}points of damage!]"
    enemy.hit your_hit

    # Retaliation.
    console.log enemy
    if enemy.life > 0
      enemy_hit = Math.rand enemy.strength + enemy.weapon
      console.log "[Your enemy hit with #{enemy_hit}points of damage!]"
      @hit enemy_hit



# # Get evil idea and swap in code words
# print "Enter your new idea: "
# idea = gets
# code_words.each do |real, code|
#   idea.gsub!( real, code )
# end
#
# # Save the jibberish to a new file
# print "File encoded.  Please enter a name for this idea: "
# idea_name = gets.strip
# File::open( "idea-" + idea_name + ".txt", "w" ) do |f|
#   f << idea
# end

# Get evil idea and swap in code words
print "Enter your new idea: "
idea = gets()
code_words.each (real, code) -> idea.replace(real, code)

# Save the jibberish to a new file
print "File encoded. Please enter a name for this idea: "
idea_name = gets().strip()
File.open "idea-#{idea_name}.txt", 'w', (file) -> file.write idea



# def wipe_mutterings_from( sentence )
#   unless sentence.respond_to? :include?
#     raise ArgumentError,
#       "cannot wipe mutterings from a #{ sentence.class }"
#   end
#   while sentence.include? '('
#     open = sentence.index( '(' )
#     close = sentence.index( ')', open )
#     sentence[open..close] = '' if close
#   end
# end

wipe_mutterings_from = (sentence) ->
  throw new Error "cannot wipe mutterings" unless sentence.indexOf
  while '(' in sentence
    open     = sentence.indexOf('(')
    close    = sentence.indexOf(')')
    sentence = "#{sentence[0...open]}#{sentence[close + 1..]}"
    sentence
1.9.3~dfsg/examples/code.coffee0000644000000000000000000000600212531364553015174 0ustar  rootroot# Functions:
square = (x) -> x * x

sum = (x, y) -> x + y

odd = (x) -> x % 2 isnt 0

even = (x) -> x % 2 is 0

run_loop = ->
  fire_events((e) -> e.stopPropagation())
  listen()
  wait()

# Objects:
dense_object_literal = one: 1, two: 2, three: 3

spaced_out_multiline_object =
  pi: 3.14159
  list: [1, 2, 3, 4]
  regex: /match[ing](every|thing|\/)/gi
  three: new Idea

  inner_obj:
    freedom: -> _.freedom()

# Arrays:
stooges = [{moe: 45}, {curly: 43}, {larry: 46}]

exponents = [((x) -> x), ((x) -> x * x), ((x) -> x * x * x)]

empty = []

multiline = [
  'line one'
  'line two'
]

# Conditionals and ternaries.
if submarine.shields_up
  full_speed_ahead()
  fire_torpedos()
else if submarine.sinking
  abandon_ship()
else
  run_away()

eldest = if 25 > 21 then liz else marge

decoration = medal_of_honor if war_hero

go_to_sleep() unless coffee

# Returning early:
race = ->
  run()
  walk()
  crawl()
  return sleep() if tired
  race()

# Conditional assignment:
good or= evil
wine and= cheese

# Nested property access and calls.
(moon.turn 360).shapes[3].move(x: 45, y: 30).position['top'].offset('x')

a = b = c = 5

# Embedded JavaScript.
callback(
  `function(e) { e.stop(); }`
)

# Try/Catch/Finally/Throw.
try
  all_hell_breaks_loose()
  dogs_and_cats_living_together()
  throw "up"
catch error
  print error
finally
  clean_up()

try all_hell_breaks_loose() catch error then print(error) finally clean_up()

# While loops, break and continue.
while demand > supply
  sell()
  restock()

while supply > demand then buy()

loop
  break if broken
  continue if continuing

# Unary operators.
!!true

# Lexical scoping.
v_1 = 5
change_a_and_set_b = ->
  v_1 = 10
  v_2 = 15
v_2 = 20

# Array comprehensions.
supper = food.capitalize() for food in ['toast', 'cheese', 'wine']

drink bottle for bottle, i in ['soda', 'wine', 'lemonade'] when even i

# Switch statements ("else" serves as a default).
activity = switch day
  when "Tuesday"   then eat_breakfast()
  when "Sunday"    then go_to_church()
  when "Saturday"  then go_to_the_park()
  when "Wednesday"
    if day is bingo_day
      go_to_bingo()
    else
      eat_breakfast()
      go_to_work()
      eat_dinner()
  else go_to_work()

# Semicolons can optionally be used instead of newlines.
wednesday = -> eat_breakfast(); go_to_work(); eat_dinner()

# Multiline strings with inner quotes.
story = "Lorem ipsum dolor \"sit\" amet, consectetuer adipiscing elit,
         sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna
         aliquam erat volutpat. Ut wisi enim ad."

# Inheritance and calling super.
class Animal
  (@name) ->

  move: (meters) ->
    alert this.name + " moved " + meters + "m."

class Snake extends Animal
  move: ->
    alert 'Slithering...'
    super 5

class Horse extends Animal
  move: ->
    alert 'Galloping...'
    super 45

sam = new Snake "Sammy the Snake"
tom = new Horse "Tommy the Horse"

sam.move()
tom.move()

# Numbers.
a_googol =  1e100
hex      =  0xff0000
negative =  -1.0
infinity =  Infinity
nan      =  NaN

# Deleting.
delete secret.identity1.9.3~dfsg/examples/computer_science/0000755000000000000000000000000012531364553016442 5ustar  rootroot1.9.3~dfsg/examples/computer_science/merge_sort.coffee0000644000000000000000000000102412531364553021756 0ustar  rootroot# Sorts an array in ascending natural order using merge sort.
merge_sort = (list) ->

  return list if list.length is 1

  pivot   = Math.floor list.length / 2
  left    = merge_sort list.slice 0, pivot
  right   = merge_sort list.slice pivot

  result = while left.length and right.length
    if left[0] < right[0] then left.shift() else right.shift()

  result.concat(left).concat(right)


# Test the function.
console.log merge_sort([3, 2, 1]).join(' ') is '1 2 3'
console.log merge_sort([9, 2, 7, 0, 1]).join(' ') is '0 1 2 7 9'1.9.3~dfsg/examples/computer_science/README0000644000000000000000000000026312531364553017323 0ustar  rootrootPorted from Nicholas Zakas' collection of computer science fundamentals, written
in JavaScript. Originals available here:

http://github.com/nzakas/computer-science-in-javascript
1.9.3~dfsg/examples/computer_science/selection_sort.coffee0000644000000000000000000000112712531364553022650 0ustar  rootroot# An in-place selection sort.
selection_sort = (list) ->
  len = list.length

  # For each item in the list.
  for i in [0...len]

    # Set the minimum to this position.
    min = i

    # Check the rest of the array to see if anything is smaller.
    min = k for v, k in list[i+1...] when v < list[min]

    # Swap if a smaller item has been found.
    [list[i], list[min]] = [list[min], list[i]] if i isnt min

  # The list is now sorted.
  list


# Test the function.
console.log selection_sort([3, 2, 1]).join(' ') is '1 2 3'
console.log selection_sort([9, 2, 7, 0, 1]).join(' ') is '0 1 2 7 9'1.9.3~dfsg/examples/computer_science/bubble_sort.coffee0000644000000000000000000000060012531364553022111 0ustar  rootroot# A bubble sort implementation, sorting the given array in-place.
bubble_sort = (list) ->
  for i in [0...list.length]
    for j in [0...list.length - i] when list[j] > list[j + 1]
      [list[j], list[j+1]] = [list[j + 1], list[j]]
  list


# Test the function.
console.log bubble_sort([3, 2, 1]).join(' ') is '1 2 3'
console.log bubble_sort([9, 2, 7, 0, 1]).join(' ') is '0 1 2 7 9'1.9.3~dfsg/examples/computer_science/luhn_algorithm.coffee0000644000000000000000000000147312531364553022634 0ustar  rootroot# Use the Luhn algorithm to validate a numeric identifier, such as credit card
# numbers, national insurance numbers, etc.
# See: http://en.wikipedia.org/wiki/Luhn_algorithm

is_valid_identifier = (identifier) ->

  sum = 0
  alt = false

  for c in identifier by -1

    # Get the next digit.
    num = parseInt c, 10

    # If it's not a valid number, abort.
    return false if isNaN num

    # If it's an alternate number...
    if alt
      num *= 2
      num = (num % 10) + 1 if num > 9

    # Flip the alternate bit.
    alt = !alt

    # Add to the rest of the sum.
    sum += num

  # Determine if it's valid.
  sum % 10 is 0


# Tests.
console.log is_valid_identifier("49927398716")      is true
console.log is_valid_identifier("4408041234567893") is true
console.log is_valid_identifier("4408041234567890") is false
1.9.3~dfsg/examples/computer_science/binary_search.coffee0000644000000000000000000000137212531364553022427 0ustar  rootroot# Uses a binary search algorithm to locate a value in the specified array.
binary_search = (items, value) ->

  start = 0
  stop  = items.length - 1
  pivot = Math.floor (start + stop) / 2

  while items[pivot] isnt value and start < stop

    # Adjust the search area.
    stop  = pivot - 1 if value < items[pivot]
    start = pivot + 1 if value > items[pivot]

    # Recalculate the pivot.
    pivot = Math.floor (stop + start) / 2

  # Make sure we've found the correct value.
  if items[pivot] is value then pivot else -1


# Test the function.
console.log  2 is binary_search [10, 20, 30, 40, 50], 30
console.log  4 is binary_search [-97, 35, 67, 88, 1200], 1200
console.log  0 is binary_search [0, 45, 70], 0
console.log -1 is binary_search [0, 45, 70], 101.9.3~dfsg/examples/computer_science/linked_list.coffee0000644000000000000000000000442412531364553022120 0ustar  rootroot# "Classic" linked list implementation that doesn't keep track of its size.
class LinkedList

  constructor: ->
    @_head = null # Pointer to the first item in the list.


  # Appends some data to the end of the list. This method traverses the existing
  # list and places the value at the end in a new node.
  add: (data) ->

    # Create a new node object to wrap the data.
    node = data: data, next: null

    current = @_head or= node

    if @_head isnt node
      current = current.next while current.next
      current.next = node

    this


  # Retrieves the data at the given position in the list.
  item: (index) ->

    # Check for out-of-bounds values.
    return null if index < 0

    current = @_head or null
    i = -1

    # Advance through the list.
    current = current.next while current and index > ++i

    # Return null if we've reached the end.
    current and current.data


  # Remove the item from the given location in the list.
  remove: (index) ->

    # Check for out-of-bounds values.
    return null if index < 0

    current = @_head or null
    i = -1

    # Special case: removing the first item.
    if index is 0
      @_head = current.next
    else

      # Find the right location.
      [previous, current] = [current, current.next] while index > ++i

      # Skip over the item to remove.
      previous.next = current.next

    # Return the value.
    current and current.data


  # Calculate the number of items in the list.
  size: ->
    current = @_head
    count = 0

    while current
      count += 1
      current = current.next

    count


  # Convert the list into an array.
  toArray: ->
    result  = []
    current = @_head

    while current
      result.push current.data
      current = current.next

    result


  # The string representation of the linked list.
  toString: -> @toArray().toString()


# Tests.
list = new LinkedList

list.add("Hi")
console.log list.size()  is 1
console.log list.item(0) is "Hi"
console.log list.item(1) is null

list = new LinkedList
list.add("zero").add("one").add("two")
console.log list.size()     is 3
console.log list.item(2)    is "two"
console.log list.remove(1)  is "one"
console.log list.item(0)    is "zero"
console.log list.item(1)    is "two"
console.log list.size()     is 2
console.log list.item(-10)  is null
1.9.3~dfsg/CNAME0000644000000000000000000000002012531364553012033 0ustar  rootrootcoffeescript.org1.9.3~dfsg/.gitignore0000644000000000000000000000022612531364553013265 0ustar  rootrootraw
presentation
test.coffee
test.litcoffee
parser.output
test/fixtures/underscore
test/*.js
examples/beautiful_code/parse.coffee
*.gem
/node_modules