PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 3.0.1
Defender Security – Malware Scanner, Login Security & Firewall v3.0.1
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / assets / js / vendor / codemirror / javascript / javascript.js

javascript.js in Defender Security – Malware Scanner, Login Security & Firewall 3.0.1, at assets/js/vendor/codemirror/javascript/javascript.js

931 lines 36.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: https://codemirror.net/LICENSE
3
4 (function(mod) {
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"));
7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror"], mod);
9 else // Plain browser env
10 mod(CodeMirror);
11 })(function(CodeMirror) {
12 "use strict";
13
14 CodeMirror.defineMode("javascript", function(config, parserConfig) {
15 var indentUnit = config.indentUnit;
16 var statementIndent = parserConfig.statementIndent;
17 var jsonldMode = parserConfig.jsonld;
18 var jsonMode = parserConfig.json || jsonldMode;
19 var isTS = parserConfig.typescript;
20 var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
21
22 // Tokenizer
23
24 var keywords = function(){
25 function kw(type) {return {type: type, style: "keyword"};}
26 var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), D = kw("keyword d");
27 var operator = kw("operator"), atom = {type: "atom", style: "atom"};
28
29 return {
30 "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
31 "return": D, "break": D, "continue": D, "new": kw("new"), "delete": C, "void": C, "throw": C,
32 "debugger": kw("debugger"), "var": kw("var"), "const": kw("var"), "let": kw("var"),
33 "function": kw("function"), "catch": kw("catch"),
34 "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
35 "in": operator, "typeof": operator, "instanceof": operator,
36 "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
37 "this": kw("this"), "class": kw("class"), "super": kw("atom"),
38 "yield": C, "export": kw("export"), "import": kw("import"), "extends": C,
39 "await": C
40 };
41 }();
42
43 var isOperatorChar = /[+\-*&%=<>!?|~^@]/;
44 var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
45
46 function readRegexp(stream) {
47 var escaped = false, next, inSet = false;
48 while ((next = stream.next()) != null) {
49 if (!escaped) {
50 if (next == "/" && !inSet) return;
51 if (next == "[") inSet = true;
52 else if (inSet && next == "]") inSet = false;
53 }
54 escaped = !escaped && next == "\\";
55 }
56 }
57
58 // Used as scratch variables to communicate multiple values without
59 // consing up tons of objects.
60 var type, content;
61 function ret(tp, style, cont) {
62 type = tp; content = cont;
63 return style;
64 }
65 function tokenBase(stream, state) {
66 var ch = stream.next();
67 if (ch == '"' || ch == "'") {
68 state.tokenize = tokenString(ch);
69 return state.tokenize(stream, state);
70 } else if (ch == "." && stream.match(/^\d[\d_]*(?:[eE][+\-]?[\d_]+)?/)) {
71 return ret("number", "number");
72 } else if (ch == "." && stream.match("..")) {
73 return ret("spread", "meta");
74 } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
75 return ret(ch);
76 } else if (ch == "=" && stream.eat(">")) {
77 return ret("=>", "operator");
78 } else if (ch == "0" && stream.match(/^(?:x[\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/)) {
79 return ret("number", "number");
80 } else if (/\d/.test(ch)) {
81 stream.match(/^[\d_]*(?:n|(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)?/);
82 return ret("number", "number");
83 } else if (ch == "/") {
84 if (stream.eat("*")) {
85 state.tokenize = tokenComment;
86 return tokenComment(stream, state);
87 } else if (stream.eat("/")) {
88 stream.skipToEnd();
89 return ret("comment", "comment");
90 } else if (expressionAllowed(stream, state, 1)) {
91 readRegexp(stream);
92 stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/);
93 return ret("regexp", "string-2");
94 } else {
95 stream.eat("=");
96 return ret("operator", "operator", stream.current());
97 }
98 } else if (ch == "`") {
99 state.tokenize = tokenQuasi;
100 return tokenQuasi(stream, state);
101 } else if (ch == "#") {
102 stream.skipToEnd();
103 return ret("error", "error");
104 } else if (ch == "<" && stream.match("!--") || ch == "-" && stream.match("->")) {
105 stream.skipToEnd()
106 return ret("comment", "comment")
107 } else if (isOperatorChar.test(ch)) {
108 if (ch != ">" || !state.lexical || state.lexical.type != ">") {
109 if (stream.eat("=")) {
110 if (ch == "!" || ch == "=") stream.eat("=")
111 } else if (/[<>*+\-]/.test(ch)) {
112 stream.eat(ch)
113 if (ch == ">") stream.eat(ch)
114 }
115 }
116 return ret("operator", "operator", stream.current());
117 } else if (wordRE.test(ch)) {
118 stream.eatWhile(wordRE);
119 var word = stream.current()
120 if (state.lastType != ".") {
121 if (keywords.propertyIsEnumerable(word)) {
122 var kw = keywords[word]
123 return ret(kw.type, kw.style, word)
124 }
125 if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false))
126 return ret("async", "keyword", word)
127 }
128 return ret("variable", "variable", word)
129 }
130 }
131
132 function tokenString(quote) {
133 return function(stream, state) {
134 var escaped = false, next;
135 if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
136 state.tokenize = tokenBase;
137 return ret("jsonld-keyword", "meta");
138 }
139 while ((next = stream.next()) != null) {
140 if (next == quote && !escaped) break;
141 escaped = !escaped && next == "\\";
142 }
143 if (!escaped) state.tokenize = tokenBase;
144 return ret("string", "string");
145 };
146 }
147
148 function tokenComment(stream, state) {
149 var maybeEnd = false, ch;
150 while (ch = stream.next()) {
151 if (ch == "/" && maybeEnd) {
152 state.tokenize = tokenBase;
153 break;
154 }
155 maybeEnd = (ch == "*");
156 }
157 return ret("comment", "comment");
158 }
159
160 function tokenQuasi(stream, state) {
161 var escaped = false, next;
162 while ((next = stream.next()) != null) {
163 if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
164 state.tokenize = tokenBase;
165 break;
166 }
167 escaped = !escaped && next == "\\";
168 }
169 return ret("quasi", "string-2", stream.current());
170 }
171
172 var brackets = "([{}])";
173 // This is a crude lookahead trick to try and notice that we're
174 // parsing the argument patterns for a fat-arrow function before we
175 // actually hit the arrow token. It only works if the arrow is on
176 // the same line as the arguments and there's no strange noise
177 // (comments) in between. Fallback is to only notice when we hit the
178 // arrow, and not declare the arguments as locals for the arrow
179 // body.
180 function findFatArrow(stream, state) {
181 if (state.fatArrowAt) state.fatArrowAt = null;
182 var arrow = stream.string.indexOf("=>", stream.start);
183 if (arrow < 0) return;
184
185 if (isTS) { // Try to skip TypeScript return type declarations after the arguments
186 var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow))
187 if (m) arrow = m.index
188 }
189
190 var depth = 0, sawSomething = false;
191 for (var pos = arrow - 1; pos >= 0; --pos) {
192 var ch = stream.string.charAt(pos);
193 var bracket = brackets.indexOf(ch);
194 if (bracket >= 0 && bracket < 3) {
195 if (!depth) { ++pos; break; }
196 if (--depth == 0) { if (ch == "(") sawSomething = true; break; }
197 } else if (bracket >= 3 && bracket < 6) {
198 ++depth;
199 } else if (wordRE.test(ch)) {
200 sawSomething = true;
201 } else if (/["'\/`]/.test(ch)) {
202 for (;; --pos) {
203 if (pos == 0) return
204 var next = stream.string.charAt(pos - 1)
205 if (next == ch && stream.string.charAt(pos - 2) != "\\") { pos--; break }
206 }
207 } else if (sawSomething && !depth) {
208 ++pos;
209 break;
210 }
211 }
212 if (sawSomething && !depth) state.fatArrowAt = pos;
213 }
214
215 // Parser
216
217 var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
218
219 function JSLexical(indented, column, type, align, prev, info) {
220 this.indented = indented;
221 this.column = column;
222 this.type = type;
223 this.prev = prev;
224 this.info = info;
225 if (align != null) this.align = align;
226 }
227
228 function inScope(state, varname) {
229 for (var v = state.localVars; v; v = v.next)
230 if (v.name == varname) return true;
231 for (var cx = state.context; cx; cx = cx.prev) {
232 for (var v = cx.vars; v; v = v.next)
233 if (v.name == varname) return true;
234 }
235 }
236
237 function parseJS(state, style, type, content, stream) {
238 var cc = state.cc;
239 // Communicate our context to the combinators.
240 // (Less wasteful than consing up a hundred closures on every call.)
241 cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
242
243 if (!state.lexical.hasOwnProperty("align"))
244 state.lexical.align = true;
245
246 while(true) {
247 var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
248 if (combinator(type, content)) {
249 while(cc.length && cc[cc.length - 1].lex)
250 cc.pop()();
251 if (cx.marked) return cx.marked;
252 if (type == "variable" && inScope(state, content)) return "variable-2";
253 return style;
254 }
255 }
256 }
257
258 // Combinator utils
259
260 var cx = {state: null, column: null, marked: null, cc: null};
261 function pass() {
262 for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
263 }
264 function cont() {
265 pass.apply(null, arguments);
266 return true;
267 }
268 function inList(name, list) {
269 for (var v = list; v; v = v.next) if (v.name == name) return true
270 return false;
271 }
272 function register(varname) {
273 var state = cx.state;
274 cx.marked = "def";
275 if (state.context) {
276 if (state.lexical.info == "var" && state.context && state.context.block) {
277 // FIXME function decls are also not block scoped
278 var newContext = registerVarScoped(varname, state.context)
279 if (newContext != null) {
280 state.context = newContext
281 return
282 }
283 } else if (!inList(varname, state.localVars)) {
284 state.localVars = new Var(varname, state.localVars)
285 return
286 }
287 }
288 // Fall through means this is global
289 if (parserConfig.globalVars && !inList(varname, state.globalVars))
290 state.globalVars = new Var(varname, state.globalVars)
291 }
292 function registerVarScoped(varname, context) {
293 if (!context) {
294 return null
295 } else if (context.block) {
296 var inner = registerVarScoped(varname, context.prev)
297 if (!inner) return null
298 if (inner == context.prev) return context
299 return new Context(inner, context.vars, true)
300 } else if (inList(varname, context.vars)) {
301 return context
302 } else {
303 return new Context(context.prev, new Var(varname, context.vars), false)
304 }
305 }
306
307 function isModifier(name) {
308 return name == "public" || name == "private" || name == "protected" || name == "abstract" || name == "readonly"
309 }
310
311 // Combinators
312
313 function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block }
314 function Var(name, next) { this.name = name; this.next = next }
315
316 var defaultVars = new Var("this", new Var("arguments", null))
317 function pushcontext() {
318 cx.state.context = new Context(cx.state.context, cx.state.localVars, false)
319 cx.state.localVars = defaultVars
320 }
321 function pushblockcontext() {
322 cx.state.context = new Context(cx.state.context, cx.state.localVars, true)
323 cx.state.localVars = null
324 }
325 function popcontext() {
326 cx.state.localVars = cx.state.context.vars
327 cx.state.context = cx.state.context.prev
328 }
329 popcontext.lex = true
330 function pushlex(type, info) {
331 var result = function() {
332 var state = cx.state, indent = state.indented;
333 if (state.lexical.type == "stat") indent = state.lexical.indented;
334 else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
335 indent = outer.indented;
336 state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
337 };
338 result.lex = true;
339 return result;
340 }
341 function poplex() {
342 var state = cx.state;
343 if (state.lexical.prev) {
344 if (state.lexical.type == ")")
345 state.indented = state.lexical.indented;
346 state.lexical = state.lexical.prev;
347 }
348 }
349 poplex.lex = true;
350
351 function expect(wanted) {
352 function exp(type) {
353 if (type == wanted) return cont();
354 else if (wanted == ";" || type == "}" || type == ")" || type == "]") return pass();
355 else return cont(exp);
356 };
357 return exp;
358 }
359
360 function statement(type, value) {
361 if (type == "var") return cont(pushlex("vardef", value), vardef, expect(";"), poplex);
362 if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
363 if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
364 if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex);
365 if (type == "debugger") return cont(expect(";"));
366 if (type == "{") return cont(pushlex("}"), pushblockcontext, block, poplex, popcontext);
367 if (type == ";") return cont();
368 if (type == "if") {
369 if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
370 cx.state.cc.pop()();
371 return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse);
372 }
373 if (type == "function") return cont(functiondef);
374 if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
375 if (type == "class" || (isTS && value == "interface")) {
376 cx.marked = "keyword"
377 return cont(pushlex("form", type == "class" ? type : value), className, poplex)
378 }
379 if (type == "variable") {
380 if (isTS && value == "declare") {
381 cx.marked = "keyword"
382 return cont(statement)
383 } else if (isTS && (value == "module" || value == "enum" || value == "type") && cx.stream.match(/^\s*\w/, false)) {
384 cx.marked = "keyword"
385 if (value == "enum") return cont(enumdef);
386 else if (value == "type") return cont(typename, expect("operator"), typeexpr, expect(";"));
387 else return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex)
388 } else if (isTS && value == "namespace") {
389 cx.marked = "keyword"
390 return cont(pushlex("form"), expression, statement, poplex)
391 } else if (isTS && value == "abstract") {
392 cx.marked = "keyword"
393 return cont(statement)
394 } else {
395 return cont(pushlex("stat"), maybelabel);
396 }
397 }
398 if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), pushblockcontext,
399 block, poplex, poplex, popcontext);
400 if (type == "case") return cont(expression, expect(":"));
401 if (type == "default") return cont(expect(":"));
402 if (type == "catch") return cont(pushlex("form"), pushcontext, maybeCatchBinding, statement, poplex, popcontext);
403 if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
404 if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
405 if (type == "async") return cont(statement)
406 if (value == "@") return cont(expression, statement)
407 return pass(pushlex("stat"), expression, expect(";"), poplex);
408 }
409 function maybeCatchBinding(type) {
410 if (type == "(") return cont(funarg, expect(")"))
411 }
412 function expression(type, value) {
413 return expressionInner(type, value, false);
414 }
415 function expressionNoComma(type, value) {
416 return expressionInner(type, value, true);
417 }
418 function parenExpr(type) {
419 if (type != "(") return pass()
420 return cont(pushlex(")"), maybeexpression, expect(")"), poplex)
421 }
422 function expressionInner(type, value, noComma) {
423 if (cx.state.fatArrowAt == cx.stream.start) {
424 var body = noComma ? arrowBodyNoComma : arrowBody;
425 if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext);
426 else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
427 }
428
429 var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
430 if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
431 if (type == "function") return cont(functiondef, maybeop);
432 if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), classExpression, poplex); }
433 if (type == "keyword c" || type == "async") return cont(noComma ? expressionNoComma : expression);
434 if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
435 if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
436 if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
437 if (type == "{") return contCommasep(objprop, "}", null, maybeop);
438 if (type == "quasi") return pass(quasi, maybeop);
439 if (type == "new") return cont(maybeTarget(noComma));
440 if (type == "import") return cont(expression);
441 return cont();
442 }
443 function maybeexpression(type) {
444 if (type.match(/[;\}\)\],]/)) return pass();
445 return pass(expression);
446 }
447
448 function maybeoperatorComma(type, value) {
449 if (type == ",") return cont(maybeexpression);
450 return maybeoperatorNoComma(type, value, false);
451 }
452 function maybeoperatorNoComma(type, value, noComma) {
453 var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
454 var expr = noComma == false ? expression : expressionNoComma;
455 if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
456 if (type == "operator") {
457 if (/\+\+|--/.test(value) || isTS && value == "!") return cont(me);
458 if (isTS && value == "<" && cx.stream.match(/^([^>]|<.*?>)*>\s*\(/, false))
459 return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, me);
460 if (value == "?") return cont(expression, expect(":"), expr);
461 return cont(expr);
462 }
463 if (type == "quasi") { return pass(quasi, me); }
464 if (type == ";") return;
465 if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
466 if (type == ".") return cont(property, me);
467 if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
468 if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) }
469 if (type == "regexp") {
470 cx.state.lastType = cx.marked = "operator"
471 cx.stream.backUp(cx.stream.pos - cx.stream.start - 1)
472 return cont(expr)
473 }
474 }
475 function quasi(type, value) {
476 if (type != "quasi") return pass();
477 if (value.slice(value.length - 2) != "${") return cont(quasi);
478 return cont(expression, continueQuasi);
479 }
480 function continueQuasi(type) {
481 if (type == "}") {
482 cx.marked = "string-2";
483 cx.state.tokenize = tokenQuasi;
484 return cont(quasi);
485 }
486 }
487 function arrowBody(type) {
488 findFatArrow(cx.stream, cx.state);
489 return pass(type == "{" ? statement : expression);
490 }
491 function arrowBodyNoComma(type) {
492 findFatArrow(cx.stream, cx.state);
493 return pass(type == "{" ? statement : expressionNoComma);
494 }
495 function maybeTarget(noComma) {
496 return function(type) {
497 if (type == ".") return cont(noComma ? targetNoComma : target);
498 else if (type == "variable" && isTS) return cont(maybeTypeArgs, noComma ? maybeoperatorNoComma : maybeoperatorComma)
499 else return pass(noComma ? expressionNoComma : expression);
500 };
501 }
502 function target(_, value) {
503 if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
504 }
505 function targetNoComma(_, value) {
506 if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
507 }
508 function maybelabel(type) {
509 if (type == ":") return cont(poplex, statement);
510 return pass(maybeoperatorComma, expect(";"), poplex);
511 }
512 function property(type) {
513 if (type == "variable") {cx.marked = "property"; return cont();}
514 }
515 function objprop(type, value) {
516 if (type == "async") {
517 cx.marked = "property";
518 return cont(objprop);
519 } else if (type == "variable" || cx.style == "keyword") {
520 cx.marked = "property";
521 if (value == "get" || value == "set") return cont(getterSetter);
522 var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params
523 if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false)))
524 cx.state.fatArrowAt = cx.stream.pos + m[0].length
525 return cont(afterprop);
526 } else if (type == "number" || type == "string") {
527 cx.marked = jsonldMode ? "property" : (cx.style + " property");
528 return cont(afterprop);
529 } else if (type == "jsonld-keyword") {
530 return cont(afterprop);
531 } else if (isTS && isModifier(value)) {
532 cx.marked = "keyword"
533 return cont(objprop)
534 } else if (type == "[") {
535 return cont(expression, maybetype, expect("]"), afterprop);
536 } else if (type == "spread") {
537 return cont(expressionNoComma, afterprop);
538 } else if (value == "*") {
539 cx.marked = "keyword";
540 return cont(objprop);
541 } else if (type == ":") {
542 return pass(afterprop)
543 }
544 }
545 function getterSetter(type) {
546 if (type != "variable") return pass(afterprop);
547 cx.marked = "property";
548 return cont(functiondef);
549 }
550 function afterprop(type) {
551 if (type == ":") return cont(expressionNoComma);
552 if (type == "(") return pass(functiondef);
553 }
554 function commasep(what, end, sep) {
555 function proceed(type, value) {
556 if (sep ? sep.indexOf(type) > -1 : type == ",") {
557 var lex = cx.state.lexical;
558 if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
559 return cont(function(type, value) {
560 if (type == end || value == end) return pass()
561 return pass(what)
562 }, proceed);
563 }
564 if (type == end || value == end) return cont();
565 if (sep && sep.indexOf(";") > -1) return pass(what)
566 return cont(expect(end));
567 }
568 return function(type, value) {
569 if (type == end || value == end) return cont();
570 return pass(what, proceed);
571 };
572 }
573 function contCommasep(what, end, info) {
574 for (var i = 3; i < arguments.length; i++)
575 cx.cc.push(arguments[i]);
576 return cont(pushlex(end, info), commasep(what, end), poplex);
577 }
578 function block(type) {
579 if (type == "}") return cont();
580 return pass(statement, block);
581 }
582 function maybetype(type, value) {
583 if (isTS) {
584 if (type == ":") return cont(typeexpr);
585 if (value == "?") return cont(maybetype);
586 }
587 }
588 function maybetypeOrIn(type, value) {
589 if (isTS && (type == ":" || value == "in")) return cont(typeexpr)
590 }
591 function mayberettype(type) {
592 if (isTS && type == ":") {
593 if (cx.stream.match(/^\s*\w+\s+is\b/, false)) return cont(expression, isKW, typeexpr)
594 else return cont(typeexpr)
595 }
596 }
597 function isKW(_, value) {
598 if (value == "is") {
599 cx.marked = "keyword"
600 return cont()
601 }
602 }
603 function typeexpr(type, value) {
604 if (value == "keyof" || value == "typeof" || value == "infer") {
605 cx.marked = "keyword"
606 return cont(value == "typeof" ? expressionNoComma : typeexpr)
607 }
608 if (type == "variable" || value == "void") {
609 cx.marked = "type"
610 return cont(afterType)
611 }
612 if (value == "|" || value == "&") return cont(typeexpr)
613 if (type == "string" || type == "number" || type == "atom") return cont(afterType);
614 if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
615 if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType)
616 if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType, afterType)
617 if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr)
618 }
619 function maybeReturnType(type) {
620 if (type == "=>") return cont(typeexpr)
621 }
622 function typeprop(type, value) {
623 if (type == "variable" || cx.style == "keyword") {
624 cx.marked = "property"
625 return cont(typeprop)
626 } else if (value == "?" || type == "number" || type == "string") {
627 return cont(typeprop)
628 } else if (type == ":") {
629 return cont(typeexpr)
630 } else if (type == "[") {
631 return cont(expect("variable"), maybetypeOrIn, expect("]"), typeprop)
632 } else if (type == "(") {
633 return pass(functiondecl, typeprop)
634 }
635 }
636 function typearg(type, value) {
637 if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg)
638 if (type == ":") return cont(typeexpr)
639 if (type == "spread") return cont(typearg)
640 return pass(typeexpr)
641 }
642 function afterType(type, value) {
643 if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
644 if (value == "|" || type == "." || value == "&") return cont(typeexpr)
645 if (type == "[") return cont(typeexpr, expect("]"), afterType)
646 if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) }
647 if (value == "?") return cont(typeexpr, expect(":"), typeexpr)
648 }
649 function maybeTypeArgs(_, value) {
650 if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
651 }
652 function typeparam() {
653 return pass(typeexpr, maybeTypeDefault)
654 }
655 function maybeTypeDefault(_, value) {
656 if (value == "=") return cont(typeexpr)
657 }
658 function vardef(_, value) {
659 if (value == "enum") {cx.marked = "keyword"; return cont(enumdef)}
660 return pass(pattern, maybetype, maybeAssign, vardefCont);
661 }
662 function pattern(type, value) {
663 if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(pattern) }
664 if (type == "variable") { register(value); return cont(); }
665 if (type == "spread") return cont(pattern);
666 if (type == "[") return contCommasep(eltpattern, "]");
667 if (type == "{") return contCommasep(proppattern, "}");
668 }
669 function proppattern(type, value) {
670 if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
671 register(value);
672 return cont(maybeAssign);
673 }
674 if (type == "variable") cx.marked = "property";
675 if (type == "spread") return cont(pattern);
676 if (type == "}") return pass();
677 if (type == "[") return cont(expression, expect(']'), expect(':'), proppattern);
678 return cont(expect(":"), pattern, maybeAssign);
679 }
680 function eltpattern() {
681 return pass(pattern, maybeAssign)
682 }
683 function maybeAssign(_type, value) {
684 if (value == "=") return cont(expressionNoComma);
685 }
686 function vardefCont(type) {
687 if (type == ",") return cont(vardef);
688 }
689 function maybeelse(type, value) {
690 if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
691 }
692 function forspec(type, value) {
693 if (value == "await") return cont(forspec);
694 if (type == "(") return cont(pushlex(")"), forspec1, poplex);
695 }
696 function forspec1(type) {
697 if (type == "var") return cont(vardef, forspec2);
698 if (type == "variable") return cont(forspec2);
699 return pass(forspec2)
700 }
701 function forspec2(type, value) {
702 if (type == ")") return cont()
703 if (type == ";") return cont(forspec2)
704 if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression, forspec2) }
705 return pass(expression, forspec2)
706 }
707 function functiondef(type, value) {
708 if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
709 if (type == "variable") {register(value); return cont(functiondef);}
710 if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, statement, popcontext);
711 if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondef)
712 }
713 function functiondecl(type, value) {
714 if (value == "*") {cx.marked = "keyword"; return cont(functiondecl);}
715 if (type == "variable") {register(value); return cont(functiondecl);}
716 if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, popcontext);
717 if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondecl)
718 }
719 function typename(type, value) {
720 if (type == "keyword" || type == "variable") {
721 cx.marked = "type"
722 return cont(typename)
723 } else if (value == "<") {
724 return cont(pushlex(">"), commasep(typeparam, ">"), poplex)
725 }
726 }
727 function funarg(type, value) {
728 if (value == "@") cont(expression, funarg)
729 if (type == "spread") return cont(funarg);
730 if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(funarg); }
731 if (isTS && type == "this") return cont(maybetype, maybeAssign)
732 return pass(pattern, maybetype, maybeAssign);
733 }
734 function classExpression(type, value) {
735 // Class expressions may have an optional name.
736 if (type == "variable") return className(type, value);
737 return classNameAfter(type, value);
738 }
739 function className(type, value) {
740 if (type == "variable") {register(value); return cont(classNameAfter);}
741 }
742 function classNameAfter(type, value) {
743 if (value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, classNameAfter)
744 if (value == "extends" || value == "implements" || (isTS && type == ",")) {
745 if (value == "implements") cx.marked = "keyword";
746 return cont(isTS ? typeexpr : expression, classNameAfter);
747 }
748 if (type == "{") return cont(pushlex("}"), classBody, poplex);
749 }
750 function classBody(type, value) {
751 if (type == "async" ||
752 (type == "variable" &&
753 (value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) &&
754 cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) {
755 cx.marked = "keyword";
756 return cont(classBody);
757 }
758 if (type == "variable" || cx.style == "keyword") {
759 cx.marked = "property";
760 return cont(isTS ? classfield : functiondef, classBody);
761 }
762 if (type == "number" || type == "string") return cont(isTS ? classfield : functiondef, classBody);
763 if (type == "[")
764 return cont(expression, maybetype, expect("]"), isTS ? classfield : functiondef, classBody)
765 if (value == "*") {
766 cx.marked = "keyword";
767 return cont(classBody);
768 }
769 if (isTS && type == "(") return pass(functiondecl, classBody)
770 if (type == ";" || type == ",") return cont(classBody);
771 if (type == "}") return cont();
772 if (value == "@") return cont(expression, classBody)
773 }
774 function classfield(type, value) {
775 if (value == "?") return cont(classfield)
776 if (type == ":") return cont(typeexpr, maybeAssign)
777 if (value == "=") return cont(expressionNoComma)
778 var context = cx.state.lexical.prev, isInterface = context && context.info == "interface"
779 return pass(isInterface ? functiondecl : functiondef)
780 }
781 function afterExport(type, value) {
782 if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
783 if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
784 if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";"));
785 return pass(statement);
786 }
787 function exportField(type, value) {
788 if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); }
789 if (type == "variable") return pass(expressionNoComma, exportField);
790 }
791 function afterImport(type) {
792 if (type == "string") return cont();
793 if (type == "(") return pass(expression);
794 return pass(importSpec, maybeMoreImports, maybeFrom);
795 }
796 function importSpec(type, value) {
797 if (type == "{") return contCommasep(importSpec, "}");
798 if (type == "variable") register(value);
799 if (value == "*") cx.marked = "keyword";
800 return cont(maybeAs);
801 }
802 function maybeMoreImports(type) {
803 if (type == ",") return cont(importSpec, maybeMoreImports)
804 }
805 function maybeAs(_type, value) {
806 if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
807 }
808 function maybeFrom(_type, value) {
809 if (value == "from") { cx.marked = "keyword"; return cont(expression); }
810 }
811 function arrayLiteral(type) {
812 if (type == "]") return cont();
813 return pass(commasep(expressionNoComma, "]"));
814 }
815 function enumdef() {
816 return pass(pushlex("form"), pattern, expect("{"), pushlex("}"), commasep(enummember, "}"), poplex, poplex)
817 }
818 function enummember() {
819 return pass(pattern, maybeAssign);
820 }
821
822 function isContinuedStatement(state, textAfter) {
823 return state.lastType == "operator" || state.lastType == "," ||
824 isOperatorChar.test(textAfter.charAt(0)) ||
825 /[,.]/.test(textAfter.charAt(0));
826 }
827
828 function expressionAllowed(stream, state, backUp) {
829 return state.tokenize == tokenBase &&
830 /^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
831 (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
832 }
833
834 // Interface
835
836 return {
837 startState: function(basecolumn) {
838 var state = {
839 tokenize: tokenBase,
840 lastType: "sof",
841 cc: [],
842 lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
843 localVars: parserConfig.localVars,
844 context: parserConfig.localVars && new Context(null, null, false),
845 indented: basecolumn || 0
846 };
847 if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
848 state.globalVars = parserConfig.globalVars;
849 return state;
850 },
851
852 token: function(stream, state) {
853 if (stream.sol()) {
854 if (!state.lexical.hasOwnProperty("align"))
855 state.lexical.align = false;
856 state.indented = stream.indentation();
857 findFatArrow(stream, state);
858 }
859 if (state.tokenize != tokenComment && stream.eatSpace()) return null;
860 var style = state.tokenize(stream, state);
861 if (type == "comment") return style;
862 state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
863 return parseJS(state, style, type, content, stream);
864 },
865
866 indent: function(state, textAfter) {
867 if (state.tokenize == tokenComment) return CodeMirror.Pass;
868 if (state.tokenize != tokenBase) return 0;
869 var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top
870 // Kludge to prevent 'maybelse' from blocking lexical scope pops
871 if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
872 var c = state.cc[i];
873 if (c == poplex) lexical = lexical.prev;
874 else if (c != maybeelse) break;
875 }
876 while ((lexical.type == "stat" || lexical.type == "form") &&
877 (firstChar == "}" || ((top = state.cc[state.cc.length - 1]) &&
878 (top == maybeoperatorComma || top == maybeoperatorNoComma) &&
879 !/^[,\.=+\-*:?[\(]/.test(textAfter))))
880 lexical = lexical.prev;
881 if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
882 lexical = lexical.prev;
883 var type = lexical.type, closing = firstChar == type;
884
885 if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info.length + 1 : 0);
886 else if (type == "form" && firstChar == "{") return lexical.indented;
887 else if (type == "form") return lexical.indented + indentUnit;
888 else if (type == "stat")
889 return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
890 else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
891 return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
892 else if (lexical.align) return lexical.column + (closing ? 0 : 1);
893 else return lexical.indented + (closing ? 0 : indentUnit);
894 },
895
896 electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
897 blockCommentStart: jsonMode ? null : "/*",
898 blockCommentEnd: jsonMode ? null : "*/",
899 blockCommentContinue: jsonMode ? null : " * ",
900 lineComment: jsonMode ? null : "//",
901 fold: "brace",
902 closeBrackets: "()[]{}''\"\"``",
903
904 helperType: jsonMode ? "json" : "javascript",
905 jsonldMode: jsonldMode,
906 jsonMode: jsonMode,
907
908 expressionAllowed: expressionAllowed,
909
910 skipExpression: function(state) {
911 var top = state.cc[state.cc.length - 1]
912 if (top == expression || top == expressionNoComma) state.cc.pop()
913 }
914 };
915 });
916
917 CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
918
919 CodeMirror.defineMIME("text/javascript", "javascript");
920 CodeMirror.defineMIME("text/ecmascript", "javascript");
921 CodeMirror.defineMIME("application/javascript", "javascript");
922 CodeMirror.defineMIME("application/x-javascript", "javascript");
923 CodeMirror.defineMIME("application/ecmascript", "javascript");
924 CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
925 CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
926 CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
927 CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
928 CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
929
930 });
931