vendor/assets/javascripts/codemirror/modes/javascript.js in codemirror-rails-3.20 vs vendor/assets/javascripts/codemirror/modes/javascript.js in codemirror-rails-3.21

- old
+ new

@@ -13,11 +13,11 @@ var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); var operator = kw("operator"), atom = {type: "atom", style: "atom"}; var jsKeywords = { "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, - "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, + "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C, "var": kw("var"), "const": kw("var"), "let": kw("var"), "function": kw("function"), "catch": kw("catch"), "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), "in": operator, "typeof": operator, "instanceof": operator, "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, @@ -52,18 +52,20 @@ return jsKeywords; }(); var isOperatorChar = /[+\-*&%=<>!?|~^]/; - function nextUntilUnescaped(stream, end) { - var escaped = false, next; + function readRegexp(stream) { + var escaped = false, next, inSet = false; while ((next = stream.next()) != null) { - if (next == end && !escaped) - return false; + if (!escaped) { + if (next == "/" && !inSet) return; + if (next == "[") inSet = true; + else if (inSet && next == "]") inSet = false; + } escaped = !escaped && next == "\\"; } - return escaped; } // Used as scratch variables to communicate multiple values without // consing up tons of objects. var type, content; @@ -81,11 +83,11 @@ } else if (ch == "." && stream.match("..")) { return ret("spread", "meta"); } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) { return ret(ch); } else if (ch == "=" && stream.eat(">")) { - return ret("=>"); + return ret("=>", "operator"); } else if (ch == "0" && stream.eat(/x/i)) { stream.eatWhile(/[\da-f]/i); return ret("number", "number"); } else if (/\d/.test(ch)) { stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); @@ -97,38 +99,42 @@ } else if (stream.eat("/")) { stream.skipToEnd(); return ret("comment", "comment"); } else if (state.lastType == "operator" || state.lastType == "keyword c" || state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) { - nextUntilUnescaped(stream, "/"); + readRegexp(stream); stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla return ret("regexp", "string-2"); } else { stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); + return ret("operator", "operator", stream.current()); } } else if (ch == "`") { state.tokenize = tokenQuasi; return tokenQuasi(stream, state); } else if (ch == "#") { stream.skipToEnd(); return ret("error", "error"); } else if (isOperatorChar.test(ch)) { stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); + return ret("operator", "operator", stream.current()); } else { stream.eatWhile(/[\w\$_]/); var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; return (known && state.lastType != ".") ? ret(known.type, known.style, word) : ret("variable", "variable", word); } } function tokenString(quote) { return function(stream, state) { - if (!nextUntilUnescaped(stream, quote)) - state.tokenize = tokenBase; + var escaped = false, next; + while ((next = stream.next()) != null) { + if (next == quote && !escaped) break; + escaped = !escaped && next == "\\"; + } + if (!escaped) state.tokenize = tokenBase; return ret("string", "string"); }; } function tokenComment(stream, state) { @@ -302,11 +308,11 @@ if (type == "keyword b") return cont(pushlex("form"), statement, poplex); if (type == "{") return cont(pushlex("}"), block, poplex); if (type == ";") return cont(); if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse); if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), forspec, poplex, statement, poplex); + if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); if (type == "variable") return cont(pushlex("stat"), maybelabel); if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), block, poplex, poplex); if (type == "case") return cont(expression, expect(":")); if (type == "default") return cont(expect(":")); @@ -325,22 +331,22 @@ return expressionInner(type, true); } function expressionInner(type, noComma) { if (cx.state.fatArrowAt == cx.stream.start) { var body = noComma ? arrowBodyNoComma : arrowBody; - if (type == "(") return cont(pushcontext, commasep(pattern, ")"), expect("=>"), body, popcontext); + if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext); else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); } var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); if (type == "function") return cont(functiondef); if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression); if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop); if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); - if (type == "[") return cont(pushlex("]"), expressionNoComma, maybeArrayComprehension, poplex, maybeop); - if (type == "{") return cont(commasep(objprop, "}"), maybeop); + if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); + if (type == "{") return contCommasep(objprop, "}", null, maybeop); return cont(); } function maybeexpression(type) { if (type.match(/[;\}\)\],]/)) return pass(); return pass(expression); @@ -363,16 +369,15 @@ if (value == "?") return cont(expression, expect(":"), expr); return cont(expr); } if (type == "quasi") { cx.cc.push(me); return quasi(value); } if (type == ";") return; - if (type == "(") return cont(commasep(expressionNoComma, ")", "call"), me); + if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); if (type == ".") return cont(property, me); if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); } function quasi(value) { - if (!value) debugger; if (value.slice(value.length - 2) != "${") return cont(); return cont(expression, continueQuasi); } function continueQuasi(type) { if (type == "}") { @@ -416,11 +421,11 @@ } function afterprop(type) { if (type == ":") return cont(expressionNoComma); if (type == "(") return pass(functiondef); } - function commasep(what, end, info) { + function commasep(what, end) { function proceed(type) { if (type == ",") { var lex = cx.state.lexical; if (lex.info == "call") lex.pos = (lex.pos || 0) + 1; return cont(what, proceed); @@ -428,14 +433,18 @@ if (type == end) return cont(); return cont(expect(end)); } return function(type) { if (type == end) return cont(); - if (info === false) return pass(what, proceed); - return pass(pushlex(end, info), what, proceed, poplex); + return pass(what, proceed); }; } + function contCommasep(what, end, info) { + for (var i = 3; i < arguments.length; i++) + cx.cc.push(arguments[i]); + return cont(pushlex(end, info), commasep(what, end), poplex); + } function block(type) { if (type == "}") return cont(); return pass(statement, block); } function maybetype(type) { @@ -447,12 +456,12 @@ function vardef() { return pass(pattern, maybetype, maybeAssign, vardefCont); } function pattern(type, value) { if (type == "variable") { register(value); return cont(); } - if (type == "[") return cont(commasep(pattern, "]")); - if (type == "{") return cont(commasep(proppattern, "}")); + if (type == "[") return contCommasep(pattern, "]"); + if (type == "{") return contCommasep(proppattern, "}"); } function proppattern(type, value) { if (type == "variable" && !cx.stream.match(/^\s*:/, false)) { register(value); return cont(maybeAssign); @@ -468,11 +477,11 @@ } function maybeelse(type, value) { if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex); } function forspec(type) { - if (type == "(") return cont(pushlex(")"), forspec1, expect(")")); + if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); } function forspec1(type) { if (type == "var") return cont(vardef, expect(";"), forspec2); if (type == ";") return cont(forspec2); if (type == "variable") return cont(formaybeinof); @@ -491,11 +500,11 @@ if (type != ")") cont(expression); } function functiondef(type, value) { if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} if (type == "variable") {register(value); return cont(functiondef);} - if (type == "(") return cont(pushcontext, commasep(funarg, ")"), statement, popcontext); + if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext); } function funarg(type) { if (type == "spread") return cont(funarg); return pass(pattern, maybetype); } @@ -504,11 +513,11 @@ } function classNameAfter(_type, value) { if (value == "extends") return cont(expression); } function objlit(type) { - if (type == "{") return cont(commasep(objprop, "}")); + if (type == "{") return contCommasep(objprop, "}"); } function afterModule(type, value) { if (type == "string") return cont(statement); if (type == "variable") { register(value); return cont(maybeFrom); } } @@ -520,20 +529,24 @@ function afterImport(type) { if (type == "string") return cont(); return pass(importSpec, maybeFrom); } function importSpec(type, value) { - if (type == "{") return cont(commasep(importSpec, "}")); + if (type == "{") return contCommasep(importSpec, "}"); if (type == "variable") register(value); return cont(); } function maybeFrom(_type, value) { if (value == "from") { cx.marked = "keyword"; return cont(expression); } } + function arrayLiteral(type) { + if (type == "]") return cont(); + return pass(expressionNoComma, maybeArrayComprehension); + } function maybeArrayComprehension(type) { - if (type == "for") return pass(comprehension); - if (type == ",") return cont(commasep(expressionNoComma, "]", false)); - return pass(commasep(expressionNoComma, "]", false)); + if (type == "for") return pass(comprehension, expect("]")); + if (type == ",") return cont(commasep(expressionNoComma, "]")); + return pass(commasep(expressionNoComma, "]")); } function comprehension(type) { if (type == "for") return cont(forspec, comprehension); if (type == "if") return cont(expression, comprehension); }