From 3645173678ed16a68beffaa000275507a3f0bae2 Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 8 Feb 2016 11:31:35 +0400 Subject: [PATCH 1/4] update treehugger --- .../treehugger/lib/acorn/dist/acorn.js | 194 +++++++++--------- .../treehugger/lib/acorn/dist/acorn_loose.js | 51 +++-- node_modules/treehugger/lib/demo.js | 42 ++-- .../treehugger/lib/treehugger/js/parse.js | 2 +- 4 files changed, 157 insertions(+), 132 deletions(-) diff --git a/node_modules/treehugger/lib/acorn/dist/acorn.js b/node_modules/treehugger/lib/acorn/dist/acorn.js index 61d3c3ca..5bc12693 100644 --- a/node_modules/treehugger/lib/acorn/dist/acorn.js +++ b/node_modules/treehugger/lib/acorn/dist/acorn.js @@ -47,7 +47,7 @@ pp.checkPropClash = function (prop, propHash) { if (this.options.ecmaVersion >= 6) { if (name === "__proto__" && kind === "init") { - if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property"); + if (propHash.proto) this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); propHash.proto = true; } return; @@ -56,7 +56,7 @@ pp.checkPropClash = function (prop, propHash) { var other = propHash[name]; if (other) { var isGetSet = kind !== "init"; - if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) this.raise(key.start, "Redefinition of property"); + if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) this.raiseRecoverable(key.start, "Redefinition of property"); } else { other = propHash[name] = { init: false, @@ -99,7 +99,7 @@ pp.parseExpression = function (noIn, refDestructuringErrors) { // operators like `+=`. pp.parseMaybeAssign = function (noIn, refDestructuringErrors, afterLeftParse) { - if (this.type == _tokentype.types._yield && this.inGenerator) return this.parseYield(); + if (this.inGenerator && this.isContextual("yield")) return this.parseYield(); var validateDestructuring = false; if (!refDestructuringErrors) { @@ -191,7 +191,7 @@ pp.parseMaybeUnary = function (refDestructuringErrors) { this.next(); node.argument = this.parseMaybeUnary(); this.checkExpressionErrors(refDestructuringErrors, true); - if (update) this.checkLVal(node.argument);else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier") this.raise(node.start, "Deleting local variable in strict mode"); + if (update) this.checkLVal(node.argument);else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier") this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); } var startPos = this.start, @@ -263,18 +263,16 @@ pp.parseExprAtom = function (refDestructuringErrors) { switch (this.type) { case _tokentype.types._super: if (!this.inFunction) this.raise(this.start, "'super' outside of function or class"); + case _tokentype.types._this: var type = this.type === _tokentype.types._this ? "ThisExpression" : "Super"; node = this.startNode(); this.next(); return this.finishNode(node, type); - case _tokentype.types._yield: - if (this.inGenerator) this.unexpected(); - case _tokentype.types.name: // quick hack to allow async and await - if (this.value == "async" && /^[ \t]+function\b/.test(this.input.slice(this.end))) { + if (this.value == "async" && /^[ \t]*(function\b|\(|\w+[ \t]*=>)/.test(this.input.slice(this.end))) { node = this.startNode(); this.next(); return this.parseExprAtom(refDestructuringErrors); @@ -313,10 +311,6 @@ pp.parseExprAtom = function (refDestructuringErrors) { case _tokentype.types.bracketL: node = this.startNode(); this.next(); - // check whether this is array comprehension or regular array - if (this.options.ecmaVersion >= 7 && this.type === _tokentype.types._for) { - return this.parseComprehension(node, false); - } node.elements = this.parseExprList(_tokentype.types.bracketR, true, true, refDestructuringErrors); return this.finishNode(node, "ArrayExpression"); @@ -364,10 +358,6 @@ pp.parseParenAndDistinguishExpression = function (canBeArrow) { if (this.options.ecmaVersion >= 6) { this.next(); - if (this.options.ecmaVersion >= 7 && this.type === _tokentype.types._for) { - return this.parseComprehension(this.startNodeAt(startPos, startLoc), true); - } - var innerStartPos = this.start, innerStartLoc = this.startLoc; var exprList = [], @@ -444,8 +434,8 @@ pp.parseNew = function () { if (this.options.ecmaVersion >= 6 && this.eat(_tokentype.types.dot)) { node.meta = meta; node.property = this.parseIdent(true); - if (node.property.name !== "target") this.raise(node.property.start, "The only valid meta property for new is new.target"); - if (!this.inFunction) this.raise(node.start, "new.target can only be used in functions"); + if (node.property.name !== "target") this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); + if (!this.inFunction) this.raiseRecoverable(node.start, "new.target can only be used in functions"); return this.finishNode(node, "MetaProperty"); } var startPos = this.start, @@ -536,13 +526,13 @@ pp.parsePropertyValue = function (prop, isPattern, isGenerator, startPos, startL var paramCount = prop.kind === "get" ? 0 : 1; if (prop.value.params.length !== paramCount) { var start = prop.value.start; - if (prop.kind === "get") this.raise(start, "getter should have no params");else this.raise(start, "setter should have exactly one param"); + if (prop.kind === "get") this.raiseRecoverable(start, "getter should have no params");else this.raiseRecoverable(start, "setter should have exactly one param"); } - if (prop.kind === "set" && prop.value.params[0].type === "RestElement") this.raise(prop.value.params[0].start, "Setter cannot use rest params"); + if (prop.kind === "set" && prop.value.params[0].type === "RestElement") this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { prop.kind = "init"; if (isPattern) { - if (this.keywords.test(prop.key.name) || (this.strict ? this.reservedWordsStrictBind : this.reservedWords).test(prop.key.name)) this.raise(prop.key.start, "Binding " + prop.key.name); + if (this.keywords.test(prop.key.name) || (this.strict ? this.reservedWordsStrictBind : this.reservedWords).test(prop.key.name) || this.inGenerator && prop.key.name == "yield") this.raiseRecoverable(prop.key.start, "Binding " + prop.key.name); prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); } else if (this.type === _tokentype.types.eq && refDestructuringErrors) { if (!refDestructuringErrors.shorthandAssign) refDestructuringErrors.shorthandAssign = this.start; @@ -581,21 +571,27 @@ pp.initFunction = function (node) { // Parse object or class method. pp.parseMethod = function (isGenerator) { - var node = this.startNode(); + var node = this.startNode(), + oldInGen = this.inGenerator; + this.inGenerator = isGenerator; this.initFunction(node); this.expect(_tokentype.types.parenL); node.params = this.parseBindingList(_tokentype.types.parenR, false, false); if (this.options.ecmaVersion >= 6) node.generator = isGenerator; this.parseFunctionBody(node, false); + this.inGenerator = oldInGen; return this.finishNode(node, "FunctionExpression"); }; // Parse arrow function expression with given parameters. pp.parseArrowExpression = function (node, params) { + var oldInGen = this.inGenerator; + this.inGenerator = false; this.initFunction(node); node.params = this.toAssignableList(params, true); this.parseFunctionBody(node, true); + this.inGenerator = oldInGen; return this.finishNode(node, "ArrowFunctionExpression"); }; @@ -611,12 +607,11 @@ pp.parseFunctionBody = function (node, isArrowFunction) { // Start a new scope with regard to labels and the `inFunction` // flag (restore them to their old value afterwards). var oldInFunc = this.inFunction, - oldInGen = this.inGenerator, oldLabels = this.labels; - this.inFunction = true;this.inGenerator = node.generator;this.labels = []; + this.inFunction = true;this.labels = []; node.body = this.parseBlock(true); node.expression = false; - this.inFunction = oldInFunc;this.inGenerator = oldInGen;this.labels = oldLabels; + this.inFunction = oldInFunc;this.labels = oldLabels; } // If this is a strict mode function, verify that argument names @@ -676,7 +671,8 @@ pp.parseIdent = function (liberal) { var node = this.startNode(); if (liberal && this.options.allowReserved == "never") liberal = false; if (this.type === _tokentype.types.name) { - if (!liberal && (this.strict ? this.reservedWordsStrict : this.reservedWords).test(this.value) && (this.options.ecmaVersion >= 6 || this.input.slice(this.start, this.end).indexOf("\\") == -1)) this.raise(this.start, "The keyword '" + this.value + "' is reserved"); + if (!liberal && (this.strict ? this.reservedWordsStrict : this.reservedWords).test(this.value) && (this.options.ecmaVersion >= 6 || this.input.slice(this.start, this.end).indexOf("\\") == -1)) this.raiseRecoverable(this.start, "The keyword '" + this.value + "' is reserved"); + if (!liberal && this.inGenerator && this.value === "yield") this.raiseRecoverable(this.start, "Can not use 'yield' as identifier inside a generator"); node.name = this.value; } else if (liberal && this.type.keyword) { node.name = this.type.keyword; @@ -702,38 +698,7 @@ pp.parseYield = function () { return this.finishNode(node, "YieldExpression"); }; -// Parses array and generator comprehensions. - -pp.parseComprehension = function (node, isGenerator) { - node.blocks = []; - while (this.type === _tokentype.types._for) { - var block = this.startNode(); - this.next(); - this.expect(_tokentype.types.parenL); - block.left = this.parseBindingAtom(); - this.checkLVal(block.left, true); - this.expectContextual("of"); - block.right = this.parseExpression(); - this.expect(_tokentype.types.parenR); - node.blocks.push(this.finishNode(block, "ComprehensionBlock")); - } - node.filter = this.eat(_tokentype.types._if) ? this.parseParenExpression() : null; - node.body = this.parseExpression(); - this.expect(isGenerator ? _tokentype.types.parenR : _tokentype.types.bracketR); - node.generator = isGenerator; - return this.finishNode(node, "ComprehensionExpression"); -}; - },{"./state":"/src\\state.js","./tokentype":"/src\\tokentype.js"}],"/src\\identifier.js":[function(_dereq_,module,exports){ -// This is a trick taken from Esprima. It turns out that, on -// non-Chrome browsers, to check whether a string is in a set, a -// predicate containing a big ugly `switch` statement is faster than -// a regular expression, and on Chrome the two are about on par. -// This function uses `eval` (non-lexical) to produce such a -// predicate from a space-separated string of words. -// -// It starts by sorting the words by length. - // Reserved word lists for various dialects of the language "use strict"; @@ -756,7 +721,7 @@ var ecma5AndLessKeywords = "break case catch continue debugger default do else f var keywords = { 5: ecma5AndLessKeywords, - 6: ecma5AndLessKeywords + " let const class extends export import yield super" + 6: ecma5AndLessKeywords + " const class extends export import super" }; exports.keywords = keywords; @@ -866,7 +831,7 @@ var _whitespace = _dereq_("./whitespace"); exports.isNewLine = _whitespace.isNewLine; exports.lineBreak = _whitespace.lineBreak; exports.lineBreakG = _whitespace.lineBreakG; -var version = "2.7.0"; +var version = "2.7.1"; exports.version = version; // The main exported interface (under `self.acorn` when in the @@ -920,6 +885,8 @@ pp.raise = function (pos, message) { throw err; }; +pp.raiseRecoverable = pp.raise; + pp.curPosition = function () { if (this.options.locations) { return new _locutil.Position(this.curLine, this.pos - this.lineStart); @@ -1161,15 +1128,15 @@ pp.parseMaybeDefault = function (startPos, startLoc, left) { pp.checkLVal = function (expr, isBinding, checkClashes) { switch (expr.type) { case "Identifier": - if (this.strict && this.reservedWordsStrictBind.test(expr.name)) this.raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); + if (this.strict && this.reservedWordsStrictBind.test(expr.name)) this.raiseRecoverable(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); if (checkClashes) { - if (_util.has(checkClashes, expr.name)) this.raise(expr.start, "Argument name clash"); + if (_util.has(checkClashes, expr.name)) this.raiseRecoverable(expr.start, "Argument name clash"); checkClashes[expr.name] = true; } break; case "MemberExpression": - if (isBinding) this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression"); + if (isBinding) this.raiseRecoverable(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression"); break; case "ObjectPattern": @@ -1274,8 +1241,8 @@ var defaultOptions = { // `ecmaVersion` indicates the ECMAScript version to parse. Must // be either 3, or 5, or 6. This influences support for strict // mode, the set of reserved words, support for getters and - // setters and other features. - ecmaVersion: 5, + // setters and other features. The default is 6. + ecmaVersion: 6, // Source type ("script" or "module") for different semantics sourceType: "script", // `onInsertedSemicolon` can be a callback that will be called @@ -1623,6 +1590,8 @@ var _state = _dereq_("./state"); var _whitespace = _dereq_("./whitespace"); +var _identifier = _dereq_("./identifier"); + var pp = _state.Parser.prototype; // ### Statement parsing @@ -1653,6 +1622,21 @@ pp.parseTopLevel = function (node) { var loopLabel = { kind: "loop" }, switchLabel = { kind: "switch" }; +pp.isLet = function () { + if (this.type !== _tokentype.types.name || this.options.ecmaVersion < 6 || this.value != "let") return false; + _whitespace.skipWhiteSpace.lastIndex = this.pos; + var skip = _whitespace.skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length, + nextCh = this.input.charCodeAt(next); + if (nextCh === 91 || nextCh == 123) return true; // '{' and '[' + if (_identifier.isIdentifierStart(nextCh, true)) { + for (var pos = next + 1; _identifier.isIdentifierChar(this.input.charCodeAt(pos, true)); ++pos) {} + var ident = this.input.slice(next, pos); + if (!this.isKeyword(ident)) return true; + } + return false; +}; + // Parse a single statement. // // If expecting a statement and finding a slash operator, parse a @@ -1662,7 +1646,13 @@ var loopLabel = { kind: "loop" }, pp.parseStatement = function (declaration, topLevel) { var starttype = this.type, - node = this.startNode(); + node = this.startNode(), + kind = undefined; + + if (this.isLet()) { + starttype = _tokentype.types._var; + kind = "let"; + } // Most types of statements are recognized by the keyword they // start with. Many are trivial to parse, some require a bit of @@ -1693,10 +1683,10 @@ pp.parseStatement = function (declaration, topLevel) { return this.parseThrowStatement(node); case _tokentype.types._try: return this.parseTryStatement(node); - case _tokentype.types._let:case _tokentype.types._const: - if (!declaration) this.unexpected(); // NOTE: falls through to _var - case _tokentype.types._var: - return this.parseVarStatement(node, starttype); + case _tokentype.types._const:case _tokentype.types._var: + kind = kind || this.value; + if (!declaration && kind != "var") this.unexpected(); + return this.parseVarStatement(node, kind); case _tokentype.types._while: return this.parseWhileStatement(node); case _tokentype.types._with: @@ -1709,7 +1699,7 @@ pp.parseStatement = function (declaration, topLevel) { case _tokentype.types._import: if (!this.options.allowImportExportEverywhere) { if (!topLevel) this.raise(this.start, "'import' and 'export' may only appear at the top level"); - // if (!this.inModule) this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); + if (!this.inModule) this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } return starttype === _tokentype.types._import ? this.parseImport(node) : this.parseExport(node); @@ -1776,13 +1766,14 @@ pp.parseForStatement = function (node) { this.labels.push(loopLabel); this.expect(_tokentype.types.parenL); if (this.type === _tokentype.types.semi) return this.parseFor(node, null); - if (this.type === _tokentype.types._var || this.type === _tokentype.types._let || this.type === _tokentype.types._const) { + var isLet = this.isLet(); + if (this.type === _tokentype.types._var || this.type === _tokentype.types._const || isLet) { var _init = this.startNode(), - varKind = this.type; + kind = isLet ? "let" : this.value; this.next(); - this.parseVar(_init, true, varKind); + this.parseVar(_init, true, kind); this.finishNode(_init, "VariableDeclaration"); - if ((this.type === _tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) && _init.declarations.length === 1 && !(varKind !== _tokentype.types._var && _init.declarations[0].init)) return this.parseForIn(node, _init); + if ((this.type === _tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) && _init.declarations.length === 1 && !(kind !== "var" && _init.declarations[0].init)) return this.parseForIn(node, _init); return this.parseFor(node, _init); } var refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 }; @@ -1846,7 +1837,7 @@ pp.parseSwitchStatement = function (node) { if (isCase) { cur.test = this.parseExpression(); } else { - if (sawDefault) this.raise(this.lastTokStart, "Multiple default clauses"); + if (sawDefault) this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); sawDefault = true; cur.test = null; } @@ -2003,13 +1994,13 @@ pp.parseForIn = function (node, init) { pp.parseVar = function (node, isFor, kind) { node.declarations = []; - node.kind = kind.keyword; + node.kind = kind; for (;;) { var decl = this.startNode(); this.parseVarId(decl); if (this.eat(_tokentype.types.eq)) { decl.init = this.parseMaybeAssign(isFor); - } else if (kind === _tokentype.types._const && !(this.type === _tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of"))) { + } else if (kind === "const" && !(this.type === _tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of"))) { this.unexpected(); } else if (decl.id.type != "Identifier" && !(isFor && (this.type === _tokentype.types._in || this.isContextual("of")))) { this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value"); @@ -2033,9 +2024,12 @@ pp.parseVarId = function (decl) { pp.parseFunction = function (node, isStatement, allowExpressionBody) { this.initFunction(node); if (this.options.ecmaVersion >= 6) node.generator = this.eat(_tokentype.types.star); + var oldInGen = this.inGenerator; + this.inGenerator = node.generator; if (isStatement || this.type === _tokentype.types.name) node.id = this.parseIdent(); this.parseFunctionParams(node); this.parseFunctionBody(node, allowExpressionBody); + this.inGenerator = oldInGen; return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression"); }; @@ -2090,7 +2084,7 @@ pp.parseClass = function (node, isStatement) { var paramCount = method.kind === "get" ? 0 : 1; if (method.value.params.length !== paramCount) { var start = method.value.start; - if (method.kind === "get") this.raise(start, "getter should have no params");else this.raise(start, "setter should have exactly one param"); + if (method.kind === "get") this.raiseRecoverable(start, "getter should have no params");else this.raiseRecoverable(start, "setter should have exactly one param"); } if (method.kind === "set" && method.value.params[0].type === "RestElement") this.raise(method.value.params[0].start, "Setter cannot use rest params"); } @@ -2125,9 +2119,10 @@ pp.parseExport = function (node) { } if (this.eat(_tokentype.types._default)) { // export default ... + var parens = this.type == _tokentype.types.parenL; var expr = this.parseMaybeAssign(); var needsSemi = true; - if (expr.type == "FunctionExpression" || expr.type == "ClassExpression") { + if (!parens && (expr.type == "FunctionExpression" || expr.type == "ClassExpression")) { needsSemi = false; if (expr.id) { expr.type = expr.type == "FunctionExpression" ? "FunctionDeclaration" : "ClassDeclaration"; @@ -2164,7 +2159,7 @@ pp.parseExport = function (node) { }; pp.shouldParseExportStatement = function () { - return this.type.keyword; + return this.type.keyword || this.isLet(); }; // Parses a comma-separated list of module exports. @@ -2249,7 +2244,7 @@ pp.parseImportSpecifiers = function () { return nodes; }; -},{"./state":"/src\\state.js","./tokentype":"/src\\tokentype.js","./whitespace":"/src\\whitespace.js"}],"/src\\tokencontext.js":[function(_dereq_,module,exports){ +},{"./identifier":"/src\\identifier.js","./state":"/src\\state.js","./tokentype":"/src\\tokentype.js","./whitespace":"/src\\whitespace.js"}],"/src\\tokencontext.js":[function(_dereq_,module,exports){ // The algorithm used to determine whether a regexp can appear at a // given point in the program is loosely based on sweet.js' approach. // See https://github.com/mozilla/sweet.js/wiki/design @@ -2601,11 +2596,21 @@ pp.readToken_slash = function () { return this.finishOp(_tokentype.types.slash, 1); }; -pp.readToken_mult_modulo = function (code) { +pp.readToken_mult_modulo_exp = function (code) { // '%*' var next = this.input.charCodeAt(this.pos + 1); - if (next === 61) return this.finishOp(_tokentype.types.assign, 2); - return this.finishOp(code === 42 ? _tokentype.types.star : _tokentype.types.modulo, 1); + var size = 1; + var tokentype = code === 42 ? _tokentype.types.star : _tokentype.types.modulo; + + // exponentiation operator ** and **= + if (this.options.ecmaVersion >= 7 && next === 42) { + ++size; + tokentype = _tokentype.types.starstar; + next = this.input.charCodeAt(this.pos + 2); + } + + if (next === 61) return this.finishOp(_tokentype.types.assign, size + 1); + return this.finishOp(tokentype, size); }; pp.readToken_pipe_amp = function (code) { @@ -2713,7 +2718,8 @@ pp.getTokenFromCode = function (code) { if (next === 120 || next === 88) return this.readRadixNumber(16); // '0x', '0X' - hex number if (this.options.ecmaVersion >= 6) { if (next === 111 || next === 79) return this.readRadixNumber(8); // '0o', '0O' - octal number - if (next === 98 || next === 66) return this.readRadixNumber(2); // '0b', '0B' - binary number + if (next === 98 || next === 66) return this.readRadixNumber(2) // '0b', '0B' - binary number + ; } // Anything else beginning with a digit is an integer, octal // number, or float. @@ -2737,7 +2743,7 @@ pp.getTokenFromCode = function (code) { case 37:case 42: // '%*' - return this.readToken_mult_modulo(code); + return this.readToken_mult_modulo_exp(code); case 124:case 38: // '|&' @@ -2855,10 +2861,10 @@ pp.readInt = function (radix, len) { for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) { var code = this.input.charCodeAt(this.pos), val = undefined; - if (code >= 97) val = code - 97 + 10; // a - else if (code >= 65) val = code - 65 + 10; // A - else if (code >= 48 && code <= 57) val = code - 48; // 0-9 - else val = Infinity; + if (code >= 97) val = code - 97 + 10 // a + ;else if (code >= 65) val = code - 65 + 10 // A + ;else if (code >= 48 && code <= 57) val = code - 48 // 0-9 + ;else val = Infinity; if (val >= radix) break; ++this.pos; total = total * radix + val; @@ -3214,7 +3220,8 @@ var types = { plusMin: new TokenType("+/-", { beforeExpr: true, binop: 9, prefix: true, startsExpr: true }), modulo: binop("%", 10), star: binop("*", 10), - slash: binop("/", 10) + slash: binop("/", 10), + starstar: binop("**", 11) }; exports.types = types; @@ -3248,7 +3255,6 @@ kw("switch"); kw("throw", beforeExpr); kw("try"); kw("var"); -kw("let"); kw("const"); kw("while", { isLoop: true }); kw("with"); @@ -3259,7 +3265,6 @@ kw("class"); kw("extends", beforeExpr); kw("export"); kw("import"); -kw("yield", { beforeExpr: true, startsExpr: true }); kw("null", startsExpr); kw("true", startsExpr); kw("false", startsExpr); @@ -3305,7 +3310,10 @@ function isNewLine(code) { } var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; + exports.nonASCIIwhitespace = nonASCIIwhitespace; +var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; +exports.skipWhiteSpace = skipWhiteSpace; },{}]},{},["/src\\index.js"])("/src\\index.js") }); diff --git a/node_modules/treehugger/lib/acorn/dist/acorn_loose.js b/node_modules/treehugger/lib/acorn/dist/acorn_loose.js index 512b2a06..032e3145 100644 --- a/node_modules/treehugger/lib/acorn/dist/acorn_loose.js +++ b/node_modules/treehugger/lib/acorn/dist/acorn_loose.js @@ -54,6 +54,19 @@ lp.parseParenExpression = function () { }; lp.parseMaybeAssign = function (noIn) { + if (this.toks.isContextual("yield")) { + var node = this.startNode(); + this.next(); + if (this.semicolon() || this.canInsertSemicolon() || this.tok.type != _.tokTypes.star && !this.tok.type.startsExpr) { + node.delegate = false; + node.argument = null; + } else { + node.delegate = this.eat(_.tokTypes.star); + node.argument = this.parseMaybeAssign(); + } + return this.finishNode(node, "YieldExpression"); + } + var start = this.storeCurrentPos(); var left = this.parseMaybeConditional(noIn); if (this.tok.type.isAssign) { @@ -193,7 +206,7 @@ lp.parseExprAtom = function () { case _.tokTypes.name: // quick hack to allow async and await - if (this.tok.value == "async" && /^[ \t]+function\b/.test(this.input.slice(this.tok.end))) { + if (this.value == "async" && /^[ \t]*(function\b|\(|\w+[ \t]*=>)/.test(this.input.slice(this.tok.end))) { node = this.startNode(); this.next(); return this.parseExprAtom(); @@ -264,18 +277,6 @@ lp.parseExprAtom = function () { case _.tokTypes._new: return this.parseNew(); - case _.tokTypes._yield: - node = this.startNode(); - this.next(); - if (this.semicolon() || this.canInsertSemicolon() || this.tok.type != _.tokTypes.star && !this.tok.type.startsExpr) { - node.delegate = false; - node.argument = null; - } else { - node.delegate = this.eat(_.tokTypes.star); - node.argument = this.parseMaybeAssign(); - } - return this.finishNode(node, "YieldExpression"); - case _.tokTypes.backQuote: return this.parseTemplate(); @@ -801,7 +802,13 @@ lp.parseTopLevel = function () { lp.parseStatement = function () { var starttype = this.tok.type, - node = this.startNode(); + node = this.startNode(), + kind = undefined; + + if (this.toks.isLet()) { + starttype = _.tokTypes._var; + kind = "let"; + } switch (starttype) { case _.tokTypes._break:case _.tokTypes._continue: @@ -832,8 +839,9 @@ lp.parseStatement = function () { this.pushCx(); this.expect(_.tokTypes.parenL); if (this.tok.type === _.tokTypes.semi) return this.parseFor(node, null); - if (this.tok.type === _.tokTypes._var || this.tok.type === _.tokTypes._let || this.tok.type === _.tokTypes._const) { - var _init = this.parseVar(true); + var isLet = this.toks.isLet(); + if (isLet || this.tok.type === _.tokTypes._var || this.tok.type === _.tokTypes._const) { + var _init = this.parseVar(true, isLet ? "let" : this.tok.value); if (_init.declarations.length === 1 && (this.tok.type === _.tokTypes._in || this.isContextual("of"))) { return this.parseForIn(node, _init); } @@ -918,9 +926,8 @@ lp.parseStatement = function () { return this.finishNode(node, "TryStatement"); case _.tokTypes._var: - case _.tokTypes._let: case _.tokTypes._const: - return this.parseVar(); + return this.parseVar(false, kind || this.tok.value); case _.tokTypes._while: this.next(); @@ -1003,9 +1010,9 @@ lp.parseForIn = function (node, init) { return this.finishNode(node, type); }; -lp.parseVar = function (noIn) { +lp.parseVar = function (noIn, kind) { var node = this.startNode(); - node.kind = this.tok.type.keyword; + node.kind = kind; this.next(); node.declarations = []; do { @@ -1114,7 +1121,7 @@ lp.parseExport = function () { this.semicolon(); return this.finishNode(node, "ExportDefaultDeclaration"); } - if (this.tok.type.keyword) { + if (this.tok.type.keyword || this.toks.isLet()) { node.declaration = this.parseStatement(); node.specifiers = []; node.source = null; @@ -1298,7 +1305,7 @@ lp.resetTo = function (pos) { this.toks.exprAllowed = !ch || /[\[\{\(,;:?\/*=+\-~!|&%^<>]/.test(ch) || /[enwfd]/.test(ch) && /\b(keywords|case|else|return|throw|new|in|(instance|type)of|delete|void)$/.test(this.input.slice(pos - 10, pos)); if (this.options.locations) { - this.toks.curLine = 1; + this.toks.curLine = 0; this.toks.lineStart = _.lineBreakG.lastIndex = 0; var match = undefined; while ((match = _.lineBreakG.exec(this.input)) && match.index < pos) { diff --git a/node_modules/treehugger/lib/demo.js b/node_modules/treehugger/lib/demo.js index d720aa81..bc8f3abf 100644 --- a/node_modules/treehugger/lib/demo.js +++ b/node_modules/treehugger/lib/demo.js @@ -1,38 +1,48 @@ require({ baseUrl: "lib" -}, ["treehugger/tree", "treehugger/traverse", "treehugger/js/parse", "jquery", +}, ["treehugger/tree", "treehugger/traverse", "treehugger/js/parse", "acorn/dist/acorn", "acorn/dist/acorn_loose", "acorn/dist/walk" -], function(tree, traverse, parsejs, jq, acorn, acorn_loose) { +], function(tree, traverse, parsejs, acorn, acorn_loose) { + var $ = document.querySelector.bind(document); + window.acorn_loose = acorn_loose; -window.acorn_loose = acorn_loose + if (localStorage.trehuggerJsVal) + $("#code").value = localStorage.trehuggerJsVal; + if (localStorage.trehuggerAnalysisVal) + $("#analysis").value = localStorage.trehuggerAnalysisVal; + window.onbeforeunload = function() { + localStorage.trehuggerJsVal = $("#code").value; + localStorage.trehuggerAnalysisVal = $("#analysis").value; + }; + function log(message) { - $("#output").val($("#output").val() + message + "\n"); + $("#output").value = $("#output").value + message + "\n"; } function exec() { - var js = $("#code").val(); - var analysisJs = $("#analysis").val(); - $("#output").val(""); + var js = $("#code").value; + var analysisJs = $("#analysis").value; + $("#output").value = ""; - var t = performance.now(); - var ast = parsejs.parse(js); - t -= performance.now(); - $("#ast").val(t + "\n" + ast.toPrettyString()); try { + var t = performance.now(); + var ast = parsejs.parse(js); + t -= performance.now(); + $("#ast").value = t + "\n" + ast.toPrettyString(); eval(analysisJs); } catch(e) { - $("#output").val("JS Error"); - console.log(e.message) + $("#output").value = "JS Error \n\t" + (e.stack || e.message); + console.log(e) } } tree.Node.prototype.log = function() { - $("#output").val(this.toPrettyString()); + $("#output").value = this.toPrettyString(); } - $("#code").keyup(exec); - $("#runbutton").click(exec); + $("#code").addEventListener("input", exec); + $("#runbutton").addEventListener("click", exec); exec(); }); diff --git a/node_modules/treehugger/lib/treehugger/js/parse.js b/node_modules/treehugger/lib/treehugger/js/parse.js index 15aa4984..92787158 100644 --- a/node_modules/treehugger/lib/treehugger/js/parse.js +++ b/node_modules/treehugger/lib/treehugger/js/parse.js @@ -216,7 +216,7 @@ exports.transform = function transform(n) { case "ArrowFunctionExpression": resultNode = tree.cons("Arrow", [tree.list(n.params.map(function(arg) { return setIdPos(arg, tree.cons("FArg", [id(arg)])); - })), tree.list(n.body.body.map(transform))]); + })), tree.list(n.body.body ? n.body.body.map(transform) : transform(n.body))]); break; case "YieldExpression": resultNode = tree.cons("Yield", [transform(n.argument)]); From b3f752e74cada9a948dce4ec49e6bc377225395a Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 8 Feb 2016 12:00:41 +0400 Subject: [PATCH 2/4] update eslint --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 48168b53..8ed3de2d 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "c9.ide.language.html.diff": "#24f3608d26", "c9.ide.language.javascript": "#c6d102471f", "c9.ide.language.javascript.immediate": "#c8b1e5767a", - "c9.ide.language.javascript.eslint": "#08f092da2a", + "c9.ide.language.javascript.eslint": "#3d3857c42e", "c9.ide.language.javascript.tern": "#bf1072b11a", "c9.ide.language.javascript.infer": "#0561c69d67", "c9.ide.language.jsonalyzer": "#bf12af3d0a", From 7c188abf07c6f7f4caddd80f874a97fc513a947f Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 8 Feb 2016 13:29:06 +0400 Subject: [PATCH 3/4] enable jsx-uses-vars by default --- .eslintrc | 3 +-- package.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.eslintrc b/.eslintrc index a81f3ae3..1f36942f 100644 --- a/.eslintrc +++ b/.eslintrc @@ -44,9 +44,8 @@ rules: no-extra-semi: 3 default-case: 3 - space-after-keywords: [1, "always"] + keyword-spacing: [1, {"before": true, "after": true, "overrides": { "catch": {"after": "maybe" } }}] space-in-parens: [1, "never"] - space-return-throw-case: [1, "always"] // space-before-function-paren: [3, {"named": "never", "anonymous": "never"}] spaced-comment: 3 // valid-jsdoc: [1, { requireReturn: false, requireParamDescription: false, prefer: { "return": "return" } }] diff --git a/package.json b/package.json index 8ed3de2d..16187266 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "c9.ide.language.html.diff": "#24f3608d26", "c9.ide.language.javascript": "#c6d102471f", "c9.ide.language.javascript.immediate": "#c8b1e5767a", - "c9.ide.language.javascript.eslint": "#3d3857c42e", + "c9.ide.language.javascript.eslint": "#562fa7b097", "c9.ide.language.javascript.tern": "#bf1072b11a", "c9.ide.language.javascript.infer": "#0561c69d67", "c9.ide.language.jsonalyzer": "#bf12af3d0a", From 03f2ee83e357e4bb250e3ee108725d0af3df593e Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 8 Feb 2016 13:43:29 +0400 Subject: [PATCH 4/4] adapt eslint_worker to new error messages --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 16187266..1a178235 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "c9.ide.language.html.diff": "#24f3608d26", "c9.ide.language.javascript": "#c6d102471f", "c9.ide.language.javascript.immediate": "#c8b1e5767a", - "c9.ide.language.javascript.eslint": "#562fa7b097", + "c9.ide.language.javascript.eslint": "#9495ab1934", "c9.ide.language.javascript.tern": "#bf1072b11a", "c9.ide.language.javascript.infer": "#0561c69d67", "c9.ide.language.jsonalyzer": "#bf12af3d0a",