diff --git a/.eslintrc b/.eslintrc index d10586d2..a81f3ae3 100644 --- a/.eslintrc +++ b/.eslintrc @@ -48,5 +48,5 @@ rules: space-in-parens: [1, "never"] space-return-throw-case: [1, "always"] // space-before-function-paren: [3, {"named": "never", "anonymous": "never"}] - spaced-line-comment: 3 + spaced-comment: 3 // valid-jsdoc: [1, { requireReturn: false, requireParamDescription: false, prefer: { "return": "return" } }] diff --git a/configs/client-default.js b/configs/client-default.js index 5e52d5d2..a9b3d229 100644 --- a/configs/client-default.js +++ b/configs/client-default.js @@ -326,8 +326,9 @@ module.exports = function(options) { "plugins/c9.ide.language.javascript.eslint/eslint", { packagePath: "plugins/c9.ide.language.python/python", - pythonPath: "/usr/local/lib/python2.7/dist-packages:/usr/local/lib/python3.4/dist-packages", + pythonPath: "/usr/local/lib/python2.7/dist-packages:/usr/local/lib/python3.4/dist-packages:/usr/local/lib/python3.5/dist-packages", }, + "plugins/c9.ide.language.go/go", { packagePath: "plugins/c9.ide.language.jsonalyzer/jsonalyzer", extendToken: extendToken, diff --git a/node_modules/ace/lib/ace/lib/es6-shim.js b/node_modules/ace/lib/ace/lib/es6-shim.js new file mode 100644 index 00000000..e81d3d63 --- /dev/null +++ b/node_modules/ace/lib/ace/lib/es6-shim.js @@ -0,0 +1,66 @@ +define(function(require, exports, module) { + function defineProp(obj, name, val) { + Object.defineProperty(obj, name, { + value: val, + enumerable: false, + writable: true, + configurable: true, + }); + } + if (!String.prototype.startsWith) { + defineProp(String.prototype, "startsWith", function(searchString, position) { + position = position || 0; + return this.lastIndexOf(searchString, position) === position; + }); + } + if (!String.prototype.endsWith) { + // Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith + defineProp(String.prototype, "endsWith", function(searchString, position) { + var subjectString = this; + if (position === undefined || position > subjectString.length) { + position = subjectString.length; + } + position -= searchString.length; + var lastIndex = subjectString.indexOf(searchString, position); + return lastIndex !== -1 && lastIndex === position; + }); + } + if (!String.prototype.repeat) { + defineProp(String.prototype, "repeat", function(count) { + var result = ""; + var string = this; + while (count > 0) { + if (count & 1) + result += string; + + if (count >>= 1) + string += string; + } + return result; + }); + } + if (!String.prototype.includes) { + defineProp(String.prototype, "includes", function(str, position) { + return this.indexOf(str, position != -1); + }); + } + if (!Object.assign) { + Object.assign = function (target) { + if (target === undefined || target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + + var output = Object(target); + for (var index = 1; index < arguments.length; index++) { + var source = arguments[index]; + if (source !== undefined && source !== null) { + Object.keys(source).forEach(function(key) { + output[key] = source[key]; + }); + } + } + return output; + }; + } + +}); diff --git a/node_modules/ace/lib/ace/lib/fixoldbrowsers.js b/node_modules/ace/lib/ace/lib/fixoldbrowsers.js index 2da9b100..50352507 100644 --- a/node_modules/ace/lib/ace/lib/fixoldbrowsers.js +++ b/node_modules/ace/lib/ace/lib/fixoldbrowsers.js @@ -15,5 +15,6 @@ define(function(require, exports, module) { require("./regexp"); require("./es5-shim"); +require("./es6-shim"); }); diff --git a/node_modules/ace/lib/ace/worker/worker.js b/node_modules/ace/lib/ace/worker/worker.js index a881496b..856a6ea9 100644 --- a/node_modules/ace/lib/ace/worker/worker.js +++ b/node_modules/ace/lib/ace/worker/worker.js @@ -210,6 +210,7 @@ window.onmessage = function(e) { else if (msg.init) { window.initBaseUrls(msg.tlns); require("ace/lib/es5-shim"); + require("ace/lib/es6-shim"); sender = window.sender = window.initSender(); var clazz = require(msg.module)[msg.classname]; main = window.main = new clazz(sender); diff --git a/node_modules/architect-build/build_support/mini_require.js b/node_modules/architect-build/build_support/mini_require.js index ca4e92f7..5c6b793c 100644 --- a/node_modules/architect-build/build_support/mini_require.js +++ b/node_modules/architect-build/build_support/mini_require.js @@ -412,7 +412,11 @@ function loadText(path, cb) { var xhr = new window.XMLHttpRequest(); xhr.open("GET", path, true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); - xhr.onload = function(e) { cb(null, xhr.responseText, xhr); }; + xhr.onload = function(e) { + if (xhr.status > 399 && xhr.status < 600) + return cb(xhr); + cb(null, xhr.responseText, xhr); + }; xhr.onabort = xhr.onerror = function(e) { cb(e); }; xhr.send(""); } @@ -425,12 +429,9 @@ var loadScript = function(path, id, callback) { if (!/https?:/.test(path)) path = host + path; var cb = function(e, val, deps) { - if (e) console.error("Couldn't load module " + module, e); + if (e) return processLoadQueue({ id: id, path: path }); - nextModule = { - name: id, - deps: deps - }; + nextModule = { name: id, deps: deps }; window.eval(val + "\n//# sourceURL=" + path); callback(null, id); return define.loaded[id]; @@ -443,9 +444,15 @@ var loadCached = function(path, cb) { return loadText(path, cb); function loadNew() { loadText(path, function(e, val, xhr) { - var m = cb(e, val); - if (val) { + try { + var m = cb(e, val); + } catch(err) { + ideCache.delete(path); + e = err; + } + if (!e) { var ETAG = xhr.getResponseHeader("ETAG"); + if (!ETAG) return; var res = new Response(val); res.headers.set("ETAG", ETAG); var req = new Request(path); @@ -467,13 +474,16 @@ var loadCached = function(path, cb) { ideCache.match(path).then(function(e) { if (!e) return loadNew(); - e.text().then(function(val) { + return e.text().then(function(val) { var deps = e.headers.get("deps"); if (typeof deps == "string") deps = deps ? deps.split(",") : []; cb(null, val, deps); }); + }).catch(function() { + loadNew(); + ideCache.delete(path); }); }; @@ -532,7 +542,11 @@ function post(path, val, progress, cb) { var xhr = new window.XMLHttpRequest(); xhr.open("POST", path, true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); - xhr.onload = function(e) { cb(null, xhr.responseText, xhr); }; + xhr.onload = function(e) { + if (xhr.status > 399 && xhr.status < 600) + return cb(xhr); + cb(null, xhr.responseText, xhr); + }; xhr.onreadystatechange = function(e) { progress(xhr.responseText, xhr); }; xhr.onabort = xhr.onerror = function(e) { cb(e); }; xhr.send(val); diff --git a/node_modules/c9/format-user-analytics.js b/node_modules/c9/format-user-analytics.js index b7612ba3..28d737fb 100644 --- a/node_modules/c9/format-user-analytics.js +++ b/node_modules/c9/format-user-analytics.js @@ -20,6 +20,7 @@ define(function(require, exports, module) { lastName: getLastName(user), name: user.fullname || user.name, pricingPlan: user.premium ? "Premium" : "Free", + referredBy: user.referrer, region: user.region }; diff --git a/node_modules/kaefer/lib/version.js b/node_modules/kaefer/lib/version.js index 01498743..c1ca0a86 100644 --- a/node_modules/kaefer/lib/version.js +++ b/node_modules/kaefer/lib/version.js @@ -2,6 +2,6 @@ define(function(require, exports, module) { // on each backwards incompatible protocol change the version number must be // increased -exports.protocol = 11; +exports.protocol = 12; }); \ No newline at end of file diff --git a/node_modules/treehugger/lib/acorn/dist/acorn.js b/node_modules/treehugger/lib/acorn/dist/acorn.js index 000e6ac5..61d3c3ca 100644 --- a/node_modules/treehugger/lib/acorn/dist/acorn.js +++ b/node_modules/treehugger/lib/acorn/dist/acorn.js @@ -25,10 +25,6 @@ var _tokentype = _dereq_("./tokentype"); var _state = _dereq_("./state"); -var _identifier = _dereq_("./identifier"); - -var _util = _dereq_("./util"); - var pp = _state.Parser.prototype; // Check if property name clashes with already added. @@ -38,8 +34,7 @@ var pp = _state.Parser.prototype; pp.checkPropClash = function (prop, propHash) { if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) return; - var key = prop.key, - name = undefined; + var key = prop.key;var name = undefined; switch (key.type) { case "Identifier": name = key.name;break; @@ -49,6 +44,7 @@ pp.checkPropClash = function (prop, propHash) { return; } var kind = prop.kind; + if (this.options.ecmaVersion >= 6) { if (name === "__proto__" && kind === "init") { if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property"); @@ -56,9 +52,9 @@ pp.checkPropClash = function (prop, propHash) { } return; } - var other = undefined; - if (_util.has(propHash, name)) { - other = propHash[name]; + name = "$" + name; + 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"); } else { @@ -86,14 +82,14 @@ pp.checkPropClash = function (prop, propHash) { // and object pattern might appear (so it's possible to raise // delayed syntax error at correct position). -pp.parseExpression = function (noIn, refShorthandDefaultPos) { +pp.parseExpression = function (noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseMaybeAssign(noIn, refShorthandDefaultPos); + var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); if (this.type === _tokentype.types.comma) { var node = this.startNodeAt(startPos, startLoc); node.expressions = [expr]; - while (this.eat(_tokentype.types.comma)) node.expressions.push(this.parseMaybeAssign(noIn, refShorthandDefaultPos)); + while (this.eat(_tokentype.types.comma)) node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)); return this.finishNode(node, "SequenceExpression"); } return expr; @@ -102,43 +98,42 @@ pp.parseExpression = function (noIn, refShorthandDefaultPos) { // Parse an assignment expression. This includes applications of // operators like `+=`. -pp.parseMaybeAssign = function (noIn, refShorthandDefaultPos, afterLeftParse) { +pp.parseMaybeAssign = function (noIn, refDestructuringErrors, afterLeftParse) { if (this.type == _tokentype.types._yield && this.inGenerator) return this.parseYield(); - var failOnShorthandAssign = undefined; - if (!refShorthandDefaultPos) { - refShorthandDefaultPos = { start: 0 }; - failOnShorthandAssign = true; - } else { - failOnShorthandAssign = false; + var validateDestructuring = false; + if (!refDestructuringErrors) { + refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 }; + validateDestructuring = true; } var startPos = this.start, startLoc = this.startLoc; if (this.type == _tokentype.types.parenL || this.type == _tokentype.types.name) this.potentialArrowAt = this.start; - var left = this.parseMaybeConditional(noIn, refShorthandDefaultPos); + var left = this.parseMaybeConditional(noIn, refDestructuringErrors); if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc); if (this.type.isAssign) { + if (validateDestructuring) this.checkPatternErrors(refDestructuringErrors, true); var node = this.startNodeAt(startPos, startLoc); node.operator = this.value; node.left = this.type === _tokentype.types.eq ? this.toAssignable(left) : left; - refShorthandDefaultPos.start = 0; // reset because shorthand default was used correctly + refDestructuringErrors.shorthandAssign = 0; // reset because shorthand default was used correctly this.checkLVal(left); this.next(); node.right = this.parseMaybeAssign(noIn); return this.finishNode(node, "AssignmentExpression"); - } else if (failOnShorthandAssign && refShorthandDefaultPos.start) { - this.unexpected(refShorthandDefaultPos.start); + } else { + if (validateDestructuring) this.checkExpressionErrors(refDestructuringErrors, true); } return left; }; // Parse a ternary conditional (`?:`) operator. -pp.parseMaybeConditional = function (noIn, refShorthandDefaultPos) { +pp.parseMaybeConditional = function (noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseExprOps(noIn, refShorthandDefaultPos); - if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr; + var expr = this.parseExprOps(noIn, refDestructuringErrors); + if (this.checkExpressionErrors(refDestructuringErrors)) return expr; if (this.eat(_tokentype.types.question)) { var node = this.startNodeAt(startPos, startLoc); node.test = expr; @@ -152,11 +147,11 @@ pp.parseMaybeConditional = function (noIn, refShorthandDefaultPos) { // Start the precedence parser. -pp.parseExprOps = function (noIn, refShorthandDefaultPos) { +pp.parseExprOps = function (noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseMaybeUnary(refShorthandDefaultPos); - if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr; + var expr = this.parseMaybeUnary(refDestructuringErrors); + if (this.checkExpressionErrors(refDestructuringErrors)) return expr; return this.parseExprOp(expr, startPos, startLoc, -1, noIn); }; @@ -187,7 +182,7 @@ pp.parseExprOp = function (left, leftStartPos, leftStartLoc, minPrec, noIn) { // Parse unary operators, both prefix and postfix. -pp.parseMaybeUnary = function (refShorthandDefaultPos) { +pp.parseMaybeUnary = function (refDestructuringErrors) { if (this.type.prefix) { var node = this.startNode(), update = this.type === _tokentype.types.incDec; @@ -195,14 +190,14 @@ pp.parseMaybeUnary = function (refShorthandDefaultPos) { node.prefix = true; this.next(); node.argument = this.parseMaybeUnary(); - if (refShorthandDefaultPos && refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start); + 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"); return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); } var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseExprSubscripts(refShorthandDefaultPos); - if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr; + var expr = this.parseExprSubscripts(refDestructuringErrors); + if (this.checkExpressionErrors(refDestructuringErrors)) return expr; while (this.type.postfix && !this.canInsertSemicolon()) { var node = this.startNodeAt(startPos, startLoc); node.operator = this.value; @@ -217,11 +212,12 @@ pp.parseMaybeUnary = function (refShorthandDefaultPos) { // Parse call, dot, and `[]`-subscript expressions. -pp.parseExprSubscripts = function (refShorthandDefaultPos) { +pp.parseExprSubscripts = function (refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseExprAtom(refShorthandDefaultPos); - if (refShorthandDefaultPos && refShorthandDefaultPos.start) return expr; + var expr = this.parseExprAtom(refDestructuringErrors); + var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"; + if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr; return this.parseSubscripts(expr, startPos, startLoc); }; @@ -261,7 +257,7 @@ pp.parseSubscripts = function (base, startPos, startLoc, noCalls) { // `new`, or an expression wrapped in punctuation like `()`, `[]`, // or `{}`. -pp.parseExprAtom = function (refShorthandDefaultPos) { +pp.parseExprAtom = function (refDestructuringErrors) { var node = undefined, canBeArrow = this.potentialArrowAt == this.start; switch (this.type) { @@ -277,6 +273,18 @@ pp.parseExprAtom = function (refShorthandDefaultPos) { 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))) { + node = this.startNode(); + this.next(); + return this.parseExprAtom(refDestructuringErrors); + } + if (this.value == "await" && /^[ \t]+[\w\x1f-\uffff]/.test(this.input.slice(this.end))) { + node = this.startNode(); + this.next(); + return this.parseExprAtom(refDestructuringErrors); + } + var startPos = this.start, startLoc = this.startLoc; var id = this.parseIdent(this.type !== _tokentype.types.name); @@ -309,11 +317,11 @@ pp.parseExprAtom = function (refShorthandDefaultPos) { if (this.options.ecmaVersion >= 7 && this.type === _tokentype.types._for) { return this.parseComprehension(node, false); } - node.elements = this.parseExprList(_tokentype.types.bracketR, true, true, refShorthandDefaultPos); + node.elements = this.parseExprList(_tokentype.types.bracketR, true, true, refDestructuringErrors); return this.finishNode(node, "ArrayExpression"); case _tokentype.types.braceL: - return this.parseObj(false, refShorthandDefaultPos); + return this.parseObj(false, refDestructuringErrors); case _tokentype.types._function: node = this.startNode(); @@ -364,7 +372,7 @@ pp.parseParenAndDistinguishExpression = function (canBeArrow) { innerStartLoc = this.startLoc; var exprList = [], first = true; - var refShorthandDefaultPos = { start: 0 }, + var refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 }, spreadStart = undefined, innerParenStart = undefined; while (this.type !== _tokentype.types.parenR) { @@ -377,7 +385,7 @@ pp.parseParenAndDistinguishExpression = function (canBeArrow) { if (this.type === _tokentype.types.parenL && !innerParenStart) { innerParenStart = this.start; } - exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem)); + exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); } } var innerEndPos = this.start, @@ -385,13 +393,14 @@ pp.parseParenAndDistinguishExpression = function (canBeArrow) { this.expect(_tokentype.types.parenR); if (canBeArrow && !this.canInsertSemicolon() && this.eat(_tokentype.types.arrow)) { + this.checkPatternErrors(refDestructuringErrors, true); if (innerParenStart) this.unexpected(innerParenStart); return this.parseParenArrowList(startPos, startLoc, exprList); } if (!exprList.length) this.unexpected(this.lastTokStart); if (spreadStart) this.unexpected(spreadStart); - if (refShorthandDefaultPos.start) this.unexpected(refShorthandDefaultPos.start); + this.checkExpressionErrors(refDestructuringErrors, true); if (exprList.length > 1) { val = this.startNodeAt(innerStartPos, innerStartLoc); @@ -421,9 +430,11 @@ pp.parseParenArrowList = function (startPos, startLoc, exprList) { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList); }; -// New's precedence is slightly tricky. It must allow its argument -// to be a `[]` or dot subscript expression, but not a call — at -// least, not without wrapping it in parentheses. Thus, it uses the +// New's precedence is slightly tricky. It must allow its argument to +// be a `[]` or dot subscript expression, but not a call — at least, +// not without wrapping it in parentheses. Thus, it uses the noCalls +// argument to parseSubscripts to prevent it from consuming the +// argument list. var empty = []; @@ -434,6 +445,7 @@ pp.parseNew = function () { 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"); return this.finishNode(node, "MetaProperty"); } var startPos = this.start, @@ -474,7 +486,7 @@ pp.parseTemplate = function () { // Parse an object literal or binding pattern. -pp.parseObj = function (isPattern, refShorthandDefaultPos) { +pp.parseObj = function (isPattern, refDestructuringErrors) { var node = this.startNode(), first = true, propHash = {}; @@ -493,23 +505,23 @@ pp.parseObj = function (isPattern, refShorthandDefaultPos) { if (this.options.ecmaVersion >= 6) { prop.method = false; prop.shorthand = false; - if (isPattern || refShorthandDefaultPos) { + if (isPattern || refDestructuringErrors) { startPos = this.start; startLoc = this.startLoc; } if (!isPattern) isGenerator = this.eat(_tokentype.types.star); } this.parsePropertyName(prop); - this.parsePropertyValue(prop, isPattern, isGenerator, startPos, startLoc, refShorthandDefaultPos); + this.parsePropertyValue(prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors); this.checkPropClash(prop, propHash); node.properties.push(this.finishNode(prop, "Property")); } return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression"); }; -pp.parsePropertyValue = function (prop, isPattern, isGenerator, startPos, startLoc, refShorthandDefaultPos) { +pp.parsePropertyValue = function (prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors) { if (this.eat(_tokentype.types.colon)) { - prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refShorthandDefaultPos); + prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); prop.kind = "init"; } else if (this.options.ecmaVersion >= 6 && this.type === _tokentype.types.parenL) { if (isPattern) this.unexpected(); @@ -526,13 +538,14 @@ pp.parsePropertyValue = function (prop, isPattern, isGenerator, startPos, startL 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 === "set" && prop.value.params[0].type === "RestElement") this.raise(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.isKeyword(prop.key.name) || this.strict && (_identifier.reservedWords.strictBind(prop.key.name) || _identifier.reservedWords.strict(prop.key.name)) || !this.options.allowReserved && this.isReservedWord(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.raise(prop.key.start, "Binding " + prop.key.name); prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); - } else if (this.type === _tokentype.types.eq && refShorthandDefaultPos) { - if (!refShorthandDefaultPos.start) refShorthandDefaultPos.start = this.start; + } else if (this.type === _tokentype.types.eq && refDestructuringErrors) { + if (!refDestructuringErrors.shorthandAssign) refDestructuringErrors.shorthandAssign = this.start; prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); } else { prop.value = prop.key; @@ -572,10 +585,7 @@ pp.parseMethod = function (isGenerator) { this.initFunction(node); this.expect(_tokentype.types.parenL); node.params = this.parseBindingList(_tokentype.types.parenR, false, false); - var allowExpressionBody = undefined; - if (this.options.ecmaVersion >= 6) { - node.generator = isGenerator; - } + if (this.options.ecmaVersion >= 6) node.generator = isGenerator; this.parseFunctionBody(node, false); return this.finishNode(node, "FunctionExpression"); }; @@ -591,8 +601,8 @@ pp.parseArrowExpression = function (node, params) { // Parse function body and check parameters. -pp.parseFunctionBody = function (node, allowExpression) { - var isExpression = allowExpression && this.type !== _tokentype.types.braceL; +pp.parseFunctionBody = function (node, isArrowFunction) { + var isExpression = isArrowFunction && this.type !== _tokentype.types.braceL; if (isExpression) { node.body = this.parseMaybeAssign(); @@ -613,13 +623,23 @@ pp.parseFunctionBody = function (node, allowExpression) { // are not repeated, and it does not try to bind the words `eval` // or `arguments`. if (this.strict || !isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) { - var nameHash = {}, - oldStrict = this.strict; + var oldStrict = this.strict; this.strict = true; if (node.id) this.checkLVal(node.id, true); - for (var i = 0; i < node.params.length; i++) { - this.checkLVal(node.params[i], true, nameHash); - }this.strict = oldStrict; + this.checkParams(node); + this.strict = oldStrict; + } else if (isArrowFunction) { + this.checkParams(node); + } +}; + +// Checks function params for various disallowed patterns such as using "eval" +// or "arguments" and duplicate parameters. + +pp.checkParams = function (node) { + var nameHash = {}; + for (var i = 0; i < node.params.length; i++) { + this.checkLVal(node.params[i], true, nameHash); } }; @@ -629,17 +649,20 @@ pp.parseFunctionBody = function (node, allowExpression) { // nothing in between them to be parsed as `null` (which is needed // for array literals). -pp.parseExprList = function (close, allowTrailingComma, allowEmpty, refShorthandDefaultPos) { +pp.parseExprList = function (close, allowTrailingComma, allowEmpty, refDestructuringErrors) { var elts = [], first = true; while (!this.eat(close)) { if (!first) { this.expect(_tokentype.types.comma); + if (this.type === close && refDestructuringErrors && !refDestructuringErrors.trailingComma) { + refDestructuringErrors.trailingComma = this.lastTokStart; + } if (allowTrailingComma && this.afterTrailingComma(close)) break; } else first = false; var elt = undefined; - if (allowEmpty && this.type === _tokentype.types.comma) elt = null;else if (this.type === _tokentype.types.ellipsis) elt = this.parseSpread(refShorthandDefaultPos);else elt = this.parseMaybeAssign(false, refShorthandDefaultPos); + if (allowEmpty && this.type === _tokentype.types.comma) elt = null;else if (this.type === _tokentype.types.ellipsis) elt = this.parseSpread(refDestructuringErrors);else elt = this.parseMaybeAssign(false, refDestructuringErrors); elts.push(elt); } return elts; @@ -653,7 +676,7 @@ 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.options.allowReserved && this.isReservedWord(this.value) || this.strict && _identifier.reservedWords.strict(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.raise(this.start, "The keyword '" + this.value + "' is reserved"); node.name = this.value; } else if (liberal && this.type.keyword) { node.name = this.type.keyword; @@ -701,7 +724,7 @@ pp.parseComprehension = function (node, isGenerator) { return this.finishNode(node, "ComprehensionExpression"); }; -},{"./identifier":"/src\\identifier.js","./state":"/src\\state.js","./tokentype":"/src\\tokentype.js","./util":"/src\\util.js"}],"/src\\identifier.js":[function(_dereq_,module,exports){ +},{"./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 @@ -711,36 +734,19 @@ pp.parseComprehension = function (node, isGenerator) { // // It starts by sorting the words by length. +// Reserved word lists for various dialects of the language + "use strict"; exports.__esModule = true; exports.isIdentifierStart = isIdentifierStart; exports.isIdentifierChar = isIdentifierChar; -// Removed to create an eval-free library - -// Reserved word lists for various dialects of the language - var reservedWords = { - 3: function anonymous(str -/**/) { -switch(str.length){case 6:switch(str){case "double":case "export":case "import":case "native":case "public":case "static":case "throws":return true}return false;case 4:switch(str){case "byte":case "char":case "enum":case "goto":case "long":return true}return false;case 5:switch(str){case "class":case "final":case "float":case "short":case "super":return true}return false;case 7:switch(str){case "boolean":case "extends":case "package":case "private":return true}return false;case 9:switch(str){case "interface":case "protected":case "transient":return true}return false;case 8:switch(str){case "abstract":case "volatile":return true}return false;case 10:return str === "implements";case 3:return str === "int";case 12:return str === "synchronized";} -}, - 5: function anonymous(str -/**/) { -switch(str.length){case 5:switch(str){case "class":case "super":case "const":return true}return false;case 6:switch(str){case "export":case "import":return true}return false;case 4:return str === "enum";case 7:return str === "extends";} -}, - 6: function anonymous(str -/**/) { -switch(str){case "enum":case "await":return true}return false; -}, - strict: function anonymous(str -/**/) { -switch(str.length){case 9:switch(str){case "interface":case "protected":return true}return false;case 7:switch(str){case "package":case "private":return true}return false;case 6:switch(str){case "public":case "static":return true}return false;case 10:return str === "implements";case 3:return str === "let";case 5:return str === "yield";} -}, - strictBind: function anonymous(str -/**/) { -switch(str){case "eval":case "arguments":return true}return false; -} + 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", + 5: "class enum extends super const export import", + 6: "enum", + strict: "implements interface let package private protected public static yield", + strictBind: "eval arguments" }; exports.reservedWords = reservedWords; @@ -749,14 +755,8 @@ exports.reservedWords = reservedWords; var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; var keywords = { - 5: function anonymous(str -/**/) { -switch(str.length){case 4:switch(str){case "case":case "else":case "with":case "null":case "true":case "void":case "this":return true}return false;case 5:switch(str){case "break":case "catch":case "throw":case "while":case "false":return true}return false;case 3:switch(str){case "for":case "try":case "var":case "new":return true}return false;case 6:switch(str){case "return":case "switch":case "typeof":case "delete":return true}return false;case 8:switch(str){case "continue":case "debugger":case "function":return true}return false;case 2:switch(str){case "do":case "if":case "in":return true}return false;case 7:switch(str){case "default":case "finally":return true}return false;case 10:return str === "instanceof";} -}, - 6: function anonymous(str -/**/) { -switch(str.length){case 5:switch(str){case "break":case "catch":case "throw":case "while":case "false":case "const":case "class":case "yield":case "super":return true}return false;case 4:switch(str){case "case":case "else":case "with":case "null":case "true":case "void":case "this":return true}return false;case 6:switch(str){case "return":case "switch":case "typeof":case "delete":case "export":case "import":return true}return false;case 3:switch(str){case "for":case "try":case "var":case "new":case "let":return true}return false;case 8:switch(str){case "continue":case "debugger":case "function":return true}return false;case 7:switch(str){case "default":case "finally":case "extends":return true}return false;case 2:switch(str){case "do":case "if":case "in":return true}return false;case 10:return str === "instanceof";} -} + 5: ecma5AndLessKeywords, + 6: ecma5AndLessKeywords + " let const class extends export import yield super" }; exports.keywords = keywords; @@ -793,11 +793,11 @@ function isIdentifierChar(code, astral) { // Git repositories for Acorn are available at // // http://marijnhaverbeke.nl/git/acorn -// https://github.com/marijnh/acorn.git +// https://github.com/ternjs/acorn.git // // Please use the [github bug tracker][ghbt] to report issues. // -// [ghbt]: https://github.com/marijnh/acorn/issues +// [ghbt]: https://github.com/ternjs/acorn/issues // // This file defines the main parser interface. The library also comes // with a [error-tolerant parser][dammit] and an @@ -815,8 +815,6 @@ exports.tokenizer = tokenizer; var _state = _dereq_("./state"); -var _options = _dereq_("./options"); - _dereq_("./parseutil"); _dereq_("./statement"); @@ -829,6 +827,9 @@ _dereq_("./location"); exports.Parser = _state.Parser; exports.plugins = _state.plugins; + +var _options = _dereq_("./options"); + exports.defaultOptions = _options.defaultOptions; var _locutil = _dereq_("./locutil"); @@ -865,7 +866,7 @@ var _whitespace = _dereq_("./whitespace"); exports.isNewLine = _whitespace.isNewLine; exports.lineBreak = _whitespace.lineBreak; exports.lineBreakG = _whitespace.lineBreakG; -var version = "2.1.1"; +var version = "2.7.0"; exports.version = version; // The main exported interface (under `self.acorn` when in the @@ -890,7 +891,7 @@ function parseExpressionAt(input, pos, options) { } // Acorn is organized as a tokenizer and a recursive-descent parser. -// The `tokenize` export provides an interface to the tokenizer. +// The `tokenizer` export provides an interface to the tokenizer. function tokenizer(input, options) { return new _state.Parser(options, input); @@ -940,7 +941,7 @@ var _whitespace = _dereq_("./whitespace"); var Position = (function () { function Position(line, col) { - _classCallCheck(this, Position); + this.line = line; this.column = col; @@ -956,7 +957,7 @@ var Position = (function () { exports.Position = Position; var SourceLocation = function SourceLocation(p, start, end) { - _classCallCheck(this, SourceLocation); + this.start = start; this.end = end; @@ -991,8 +992,6 @@ var _tokentype = _dereq_("./tokentype"); var _state = _dereq_("./state"); -var _identifier = _dereq_("./identifier"); - var _util = _dereq_("./util"); var pp = _state.Parser.prototype; @@ -1006,7 +1005,6 @@ pp.toAssignable = function (node, isBinding) { case "Identifier": case "ObjectPattern": case "ArrayPattern": - case "AssignmentPattern": break; case "ObjectExpression": @@ -1026,10 +1024,16 @@ pp.toAssignable = function (node, isBinding) { case "AssignmentExpression": if (node.operator === "=") { node.type = "AssignmentPattern"; - delete node.operator; + delete node.operator + // falls through to AssignmentPattern + ; } else { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); + break; } + + case "AssignmentPattern": + if (node.right.type === "YieldExpression") this.raise(node.right.start, "Yield expression cannot be a default value"); break; case "ParenthesizedExpression": @@ -1061,6 +1065,8 @@ pp.toAssignableList = function (exprList, isBinding) { if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern") this.unexpected(arg.start); --end; } + + if (isBinding && last.type === "RestElement" && last.argument.type !== "Identifier") this.unexpected(last.argument.start); } for (var i = 0; i < end; i++) { var elt = exprList[i]; @@ -1071,17 +1077,20 @@ pp.toAssignableList = function (exprList, isBinding) { // Parses spread element. -pp.parseSpread = function (refShorthandDefaultPos) { +pp.parseSpread = function (refDestructuringErrors) { var node = this.startNode(); this.next(); - node.argument = this.parseMaybeAssign(refShorthandDefaultPos); + node.argument = this.parseMaybeAssign(refDestructuringErrors); return this.finishNode(node, "SpreadElement"); }; -pp.parseRest = function () { +pp.parseRest = function (allowNonIdent) { var node = this.startNode(); this.next(); - node.argument = this.type === _tokentype.types.name || this.type === _tokentype.types.bracketL ? this.parseBindingAtom() : this.unexpected(); + + // RestElement inside of a function parameter must be an identifier + if (allowNonIdent) node.argument = this.type === _tokentype.types.name ? this.parseIdent() : this.unexpected();else node.argument = this.type === _tokentype.types.name || this.type === _tokentype.types.bracketL ? this.parseBindingAtom() : this.unexpected(); + return this.finishNode(node, "RestElement"); }; @@ -1107,7 +1116,7 @@ pp.parseBindingAtom = function () { } }; -pp.parseBindingList = function (close, allowEmpty, allowTrailingComma) { +pp.parseBindingList = function (close, allowEmpty, allowTrailingComma, allowNonIdent) { var elts = [], first = true; while (!this.eat(close)) { @@ -1117,7 +1126,7 @@ pp.parseBindingList = function (close, allowEmpty, allowTrailingComma) { } else if (allowTrailingComma && this.afterTrailingComma(close)) { break; } else if (this.type === _tokentype.types.ellipsis) { - var rest = this.parseRest(); + var rest = this.parseRest(allowNonIdent); this.parseBindingListItem(rest); elts.push(rest); this.expect(close); @@ -1139,9 +1148,8 @@ pp.parseBindingListItem = function (param) { pp.parseMaybeDefault = function (startPos, startLoc, left) { left = left || this.parseBindingAtom(); - if (!this.eat(_tokentype.types.eq)) return left; + if (this.options.ecmaVersion < 6 || !this.eat(_tokentype.types.eq)) return left; var node = this.startNodeAt(startPos, startLoc); - node.operator = "="; node.left = left; node.right = this.parseMaybeAssign(); return this.finishNode(node, "AssignmentPattern"); @@ -1153,9 +1161,9 @@ pp.parseMaybeDefault = function (startPos, startLoc, left) { pp.checkLVal = function (expr, isBinding, checkClashes) { switch (expr.type) { case "Identifier": - if (this.strict && (_identifier.reservedWords.strictBind(expr.name) || _identifier.reservedWords.strict(expr.name))) this.raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); + if (this.strict && this.reservedWordsStrictBind.test(expr.name)) this.raise(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 in strict mode"); + if (_util.has(checkClashes, expr.name)) this.raise(expr.start, "Argument name clash"); checkClashes[expr.name] = true; } break; @@ -1193,7 +1201,7 @@ pp.checkLVal = function (expr, isBinding, checkClashes) { } }; -},{"./identifier":"/src\\identifier.js","./state":"/src\\state.js","./tokentype":"/src\\tokentype.js","./util":"/src\\util.js"}],"/src\\node.js":[function(_dereq_,module,exports){ +},{"./state":"/src\\state.js","./tokentype":"/src\\tokentype.js","./util":"/src\\util.js"}],"/src\\node.js":[function(_dereq_,module,exports){ "use strict"; exports.__esModule = true; @@ -1205,7 +1213,7 @@ var _state = _dereq_("./state"); var _locutil = _dereq_("./locutil"); var Node = function Node(parser, pos, loc) { - _classCallCheck(this, Node); + this.type = ""; this.start = pos; @@ -1279,11 +1287,11 @@ var defaultOptions = { // `onTrailingComma` is similar to `onInsertedSemicolon`, but for // trailing commas. onTrailingComma: null, - // By default, reserved words are not enforced. Disable - // `allowReserved` to enforce them. When this option has the - // value "never", reserved words and keywords can also not be - // used as property names. - allowReserved: true, + // By default, reserved words are only enforced if ecmaVersion >= 5. + // Set `allowReserved` to a boolean value to explicitly turn this on + // an off. When this option has the value "never", reserved words + // and keywords can also not be used as property names. + allowReserved: null, // When enabled, a return at the top level is not considered an // error. allowReturnOutsideFunction: false, @@ -1300,9 +1308,9 @@ var defaultOptions = { locations: true, // A function can be passed as `onToken` option, which will // cause Acorn to call that function with object in the same - // format as tokenize() returns. Note that you are not - // allowed to call the parser from the callback—that will - // corrupt its internal state. + // format as tokens returned from `tokenizer().getToken()`. Note + // that you are not allowed to call the parser from the + // callback—that will corrupt its internal state. onToken: null, // A function can be passed as `onComment` option, which will // cause Acorn to call that function with `(block, text, start, @@ -1349,7 +1357,9 @@ function getOptions(opts) { var options = {}; for (var opt in defaultOptions) { options[opt] = opts && _util.has(opts, opt) ? opts[opt] : defaultOptions[opt]; - }if (_util.isArray(options.onToken)) { + }if (options.allowReserved == null) options.allowReserved = options.ecmaVersion < 5; + + if (_util.isArray(options.onToken)) { (function () { var tokens = options.onToken; options.onToken = function (token) { @@ -1466,6 +1476,18 @@ pp.unexpected = function (pos) { this.raise(pos != null ? pos : this.start, "Unexpected token"); }; +pp.checkPatternErrors = function (refDestructuringErrors, andThrow) { + var pos = refDestructuringErrors && refDestructuringErrors.trailingComma; + if (!andThrow) return !!pos; + if (pos) this.raise(pos, "Trailing comma is not permitted in destructuring patterns"); +}; + +pp.checkExpressionErrors = function (refDestructuringErrors, andThrow) { + var pos = refDestructuringErrors && refDestructuringErrors.shorthandAssign; + if (!andThrow) return !!pos; + if (pos) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns"); +}; + },{"./state":"/src\\state.js","./tokentype":"/src\\tokentype.js","./whitespace":"/src\\whitespace.js"}],"/src\\state.js":[function(_dereq_,module,exports){ "use strict"; @@ -1485,19 +1507,31 @@ var _options = _dereq_("./options"); var plugins = {}; exports.plugins = plugins; +function keywordRegexp(words) { + return new RegExp("^(" + words.replace(/ /g, "|") + ")$"); +} var Parser = (function () { function Parser(options, input, startPos) { - _classCallCheck(this, Parser); - this.options = _options.getOptions(options); - this.sourceFile = this.options.sourceFile; - this.isKeyword = _identifier.keywords[this.options.ecmaVersion >= 6 ? 6 : 5]; - this.isReservedWord = _identifier.reservedWords[this.options.ecmaVersion]; + + this.options = options = _options.getOptions(options); + this.sourceFile = options.sourceFile; + this.keywords = keywordRegexp(_identifier.keywords[options.ecmaVersion >= 6 ? 6 : 5]); + var reserved = options.allowReserved ? "" : _identifier.reservedWords[options.ecmaVersion] + (options.sourceType == "module" ? " await" : ""); + this.reservedWords = keywordRegexp(reserved); + var reservedStrict = (reserved ? reserved + " " : "") + _identifier.reservedWords.strict; + this.reservedWordsStrict = keywordRegexp(reservedStrict); + this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + _identifier.reservedWords.strictBind); this.input = String(input); + // Used to signal to callers of `readWord1` whether the word + // contained any escape sequences. This is needed because words with + // escape sequences must not be interpreted as keywords. + this.containsEsc = false; + // Load plugins - this.loadPlugins(this.options.plugins); + this.loadPlugins(options.plugins); // Set up token state @@ -1533,7 +1567,7 @@ var Parser = (function () { this.exprAllowed = true; // Figure out if it's a module code. - this.strict = this.inModule = this.options.sourceType === "module"; + this.strict = this.inModule = options.sourceType === "module"; // Used to signify the start of a potential arrow function this.potentialArrowAt = -1; @@ -1544,9 +1578,19 @@ var Parser = (function () { this.labels = []; // If enabled, skip leading hashbang line. - if (this.pos === 0 && this.options.allowHashBang && this.input.slice(0, 2) === "#!") this.skipLineComment(2); + if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") this.skipLineComment(2); } + // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them + + Parser.prototype.isKeyword = function isKeyword(word) { + return this.keywords.test(word); + }; + + Parser.prototype.isReservedWord = function isReservedWord(word) { + return this.reservedWords.test(word); + }; + Parser.prototype.extend = function extend(name, f) { this[name] = f(this[name]); }; @@ -1665,7 +1709,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); @@ -1741,14 +1785,15 @@ pp.parseForStatement = function (node) { 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); return this.parseFor(node, _init); } - var refShorthandDefaultPos = { start: 0 }; - var init = this.parseExpression(true, refShorthandDefaultPos); + var refDestructuringErrors = { shorthandAssign: 0, trailingComma: 0 }; + var init = this.parseExpression(true, refDestructuringErrors); if (this.type === _tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) { + this.checkPatternErrors(refDestructuringErrors, true); this.toAssignable(init); this.checkLVal(init); return this.parseForIn(node, init); - } else if (refShorthandDefaultPos.start) { - this.unexpected(refShorthandDefaultPos.start); + } else { + this.checkExpressionErrors(refDestructuringErrors, true); } return this.parseFor(node, init); }; @@ -1840,11 +1885,9 @@ pp.parseTryStatement = function (node) { clause.param = this.parseBindingAtom(); this.checkLVal(clause.param, true); this.expect(_tokentype.types.parenR); - clause.guard = null; clause.body = this.parseBlock(); node.handler = this.finishNode(clause, "CatchClause"); } - node.guardedHandlers = empty; node.finalizer = this.eat(_tokentype.types._finally) ? this.parseBlock() : null; if (!node.handler && !node.finalizer) this.raise(node.start, "Missing catch or finally clause"); return this.finishNode(node, "TryStatement"); @@ -1998,7 +2041,7 @@ pp.parseFunction = function (node, isStatement, allowExpressionBody) { pp.parseFunctionParams = function (node) { this.expect(_tokentype.types.parenL); - node.params = this.parseBindingList(_tokentype.types.parenR, false, false); + node.params = this.parseBindingList(_tokentype.types.parenR, false, false, true); }; // Parse a class declaration or literal (depending on the @@ -2049,6 +2092,7 @@ pp.parseClass = function (node, isStatement) { 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 === "set" && method.value.params[0].type === "RestElement") this.raise(method.value.params[0].start, "Setter cannot use rest params"); } } node.body = this.finishNode(classBody, "ClassBody"); @@ -2105,6 +2149,13 @@ pp.parseExport = function (node) { if (this.eatContextual("from")) { node.source = this.type === _tokentype.types.string ? this.parseExprAtom() : this.unexpected(); } else { + // check for keywords used as local names + for (var i = 0; i < node.specifiers.length; i++) { + if (this.keywords.test(node.specifiers[i].local.name) || this.reservedWords.test(node.specifiers[i].local.name)) { + this.unexpected(node.specifiers[i].local.start); + } + } + node.source = null; } this.semicolon(); @@ -2145,7 +2196,6 @@ pp.parseImport = function (node) { if (this.type === _tokentype.types.string) { node.specifiers = empty; node.source = this.parseExprAtom(); - node.kind = ""; } else { node.specifiers = this.parseImportSpecifiers(); this.expectContextual("from"); @@ -2186,7 +2236,13 @@ pp.parseImportSpecifiers = function () { var node = this.startNode(); node.imported = this.parseIdent(true); - node.local = this.eatContextual("as") ? this.parseIdent() : node.imported; + if (this.eatContextual("as")) { + node.local = this.parseIdent(); + } else { + node.local = node.imported; + if (this.isKeyword(node.local.name)) this.unexpected(node.local.start); + if (this.reservedWordsStrict.test(node.local.name)) this.raise(node.local.start, "The keyword '" + node.local.name + "' is reserved"); + } this.checkLVal(node.local, true); nodes.push(this.finishNode(node, "ImportSpecifier")); } @@ -2211,7 +2267,7 @@ var _tokentype = _dereq_("./tokentype"); var _whitespace = _dereq_("./whitespace"); var TokContext = function TokContext(token, isExpr, preserveSpace, override) { - _classCallCheck(this, TokContext); + this.token = token; this.isExpr = !!isExpr; @@ -2326,7 +2382,7 @@ var _whitespace = _dereq_("./whitespace"); // used for the onToken callback and the external tokenizer. var Token = function Token(p) { - _classCallCheck(this, Token); + this.type = p.type; this.value = p.value; @@ -2720,13 +2776,13 @@ pp.finishOp = function (type, size) { // Parse a regular expression. Some context-awareness is necessary, // since a '/' inside a '[]' set does not end the expression. -function tryCreateRegexp(src, flags, throwErrorAt) { +function tryCreateRegexp(src, flags, throwErrorAt, parser) { try { return new RegExp(src, flags); } catch (e) { if (throwErrorAt !== undefined) { - if (e instanceof SyntaxError) this.raise(throwErrorAt, "Error parsing regular expression: " + e.message); - this.raise(e); + if (e instanceof SyntaxError) parser.raise(throwErrorAt, "Error parsing regular expression: " + e.message); + throw e; } } } @@ -2756,8 +2812,8 @@ pp.readRegexp = function () { var mods = this.readWord1(); var tmp = content; if (mods) { - var validFlags = /^[gmsiy]*$/; - if (this.options.ecmaVersion >= 6) validFlags = /^[gmsiyu]*$/; + var validFlags = /^[gim]*$/; + if (this.options.ecmaVersion >= 6) validFlags = /^[gimuy]*$/; if (!validFlags.test(mods)) this.raise(start, "Invalid regular expression flag"); if (mods.indexOf("u") >= 0 && !regexpUnicodeSupport) { // Replace each astral symbol and every Unicode escape sequence that @@ -2768,7 +2824,7 @@ pp.readRegexp = function () { // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a // perfectly valid pattern that is equivalent to `[a-b]`, but it would // be replaced by `[x-b]` which throws an error. - tmp = tmp.replace(/\\u\{([0-9a-fA-F]+)\}/g, function (match, code, offset) { + tmp = tmp.replace(/\\u\{([0-9a-fA-F]+)\}/g, function (_match, code, offset) { code = Number("0x" + code); if (code > 0x10FFFF) _this.raise(start + offset + 3, "Code point out of bounds"); return "x"; @@ -2781,7 +2837,7 @@ pp.readRegexp = function () { // Rhino's regular expression parser is flaky and throws uncatchable exceptions, // so don't do detection if we are running under Rhino if (!isRhino) { - tryCreateRegexp(tmp, undefined, start); + tryCreateRegexp(tmp, undefined, start, this); // Get a regular expression object for this pattern-flag pair, or `null` in // case the current environment doesn't support the flags it uses. value = tryCreateRegexp(content, mods); @@ -2985,7 +3041,7 @@ pp.readEscapedChar = function (inTemplate) { octalStr = octalStr.slice(0, -1); octal = parseInt(octalStr, 8); } - if (octal > 0 && (this.strict || inTemplate)) { + if (octalStr !== "0" && (this.strict || inTemplate)) { this.raise(this.pos - 2, "Octal literal in strict mode"); } this.pos += octalStr.length - 1; @@ -3004,20 +3060,14 @@ pp.readHexChar = function (len) { return n; }; -// Used to signal to callers of `readWord1` whether the word -// contained any escape sequences. This is needed because words with -// escape sequences must not be interpreted as keywords. - -var containsEsc; - -// Read an identifier, and return it as a string. Sets `containsEsc` +// Read an identifier, and return it as a string. Sets `this.containsEsc` // to whether the word contained a '\u' escape. // // Incrementally adds only escaped chars, adding other chunks as-is // as a micro-optimization. pp.readWord1 = function () { - containsEsc = false; + this.containsEsc = false; var word = "", first = true, chunkStart = this.pos; @@ -3028,7 +3078,7 @@ pp.readWord1 = function () { this.pos += ch <= 0xffff ? 1 : 2; } else if (ch === 92) { // "\" - containsEsc = true; + this.containsEsc = true; word += this.input.slice(chunkStart, this.pos); var escStart = this.pos; if (this.input.charCodeAt(++this.pos) != 117) // "u" @@ -3052,7 +3102,7 @@ pp.readWord1 = function () { pp.readWord = function () { var word = this.readWord1(); var type = _tokentype.types.name; - if ((this.options.ecmaVersion >= 6 || !containsEsc) && this.isKeyword(word)) type = _tokentype.keywords[word]; + if ((this.options.ecmaVersion >= 6 || !this.containsEsc) && this.keywords.test(word)) type = _tokentype.keywords[word]; return this.finishToken(type, word); }; @@ -3071,6 +3121,11 @@ pp.readWord = function () { // be followed by an expression (thus, a slash after them would be a // regular expression). // +// The `startsExpr` property is used to check if the token ends a +// `yield` expression. It is set on all token types that either can +// directly start an expression (like a quotation mark) or can +// continue an expression (like the body of a string). +// // `isLoop` marks a keyword as starting a loop, which is important // to know when parsing a label, in order to allow or disallow // continue jumps to that label. @@ -3084,7 +3139,6 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons var TokenType = function TokenType(label) { var conf = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; - _classCallCheck(this, TokenType); this.label = label; this.keyword = conf.keyword; @@ -3183,7 +3237,7 @@ kw("catch"); kw("continue"); kw("debugger"); kw("default", beforeExpr); -kw("do", { isLoop: true }); +kw("do", { isLoop: true, beforeExpr: true }); kw("else", beforeExpr); kw("finally"); kw("for", { isLoop: true }); @@ -3255,5 +3309,4 @@ exports.nonASCIIwhitespace = nonASCIIwhitespace; },{}]},{},["/src\\index.js"])("/src\\index.js") }); - -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/node_modules/treehugger/lib/acorn/dist/acorn_loose.js b/node_modules/treehugger/lib/acorn/dist/acorn_loose.js index f402ccf6..512b2a06 100644 --- a/node_modules/treehugger/lib/acorn/dist/acorn_loose.js +++ b/node_modules/treehugger/lib/acorn/dist/acorn_loose.js @@ -1,8 +1,9 @@ define(["require", "exports", "module", "./acorn"], function(require, exports, module) { + (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}(g.acorn || (g.acorn = {})).loose = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 6) return expr; - default: return this.dummyIdent(); } @@ -200,6 +192,17 @@ lp.parseExprAtom = function () { return this.finishNode(node, type); 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))) { + node = this.startNode(); + this.next(); + return this.parseExprAtom(); + } + if (this.tok.value == "await" && /^[ \t]+[\w\x1f-\uffff]/.test(this.input.slice(this.tok.end))) { + node = this.startNode(); + this.next(); + return this.parseExprAtom(); + } var start = this.storeCurrentPos(); var id = this.parseIdent(); return this.eat(_.tokTypes.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id]) : id; @@ -440,32 +443,29 @@ lp.initFunction = function (node) { // if possible. lp.toAssignable = function (node, binding) { - if (this.options.ecmaVersion >= 6 && node) { - switch (node.type) { - case "ObjectExpression": - node.type = "ObjectPattern"; - var props = node.properties; - for (var i = 0; i < props.length; i++) { - this.toAssignable(props[i].value, binding); - }break; - - case "ArrayExpression": - node.type = "ArrayPattern"; - this.toAssignableList(node.elements, binding); - break; - - case "SpreadElement": - node.type = "RestElement"; - node.argument = this.toAssignable(node.argument, binding); - break; - - case "AssignmentExpression": - node.type = "AssignmentPattern"; - delete node.operator; - break; + if (!node || node.type == "Identifier" || node.type == "MemberExpression" && !binding) {} else if (node.type == "ParenthesizedExpression") { + node.expression = this.toAssignable(node.expression, binding); + } else if (this.options.ecmaVersion < 6) { + return this.dummyIdent(); + } else if (node.type == "ObjectExpression") { + node.type = "ObjectPattern"; + var props = node.properties; + for (var i = 0; i < props.length; i++) { + props[i].value = this.toAssignable(props[i].value, binding); } + } else if (node.type == "ArrayExpression") { + node.type = "ArrayPattern"; + this.toAssignableList(node.elements, binding); + } else if (node.type == "SpreadElement") { + node.type = "RestElement"; + node.argument = this.toAssignable(node.argument, binding); + } else if (node.type == "AssignmentExpression") { + node.type = "AssignmentPattern"; + delete node.operator; + } else { + return this.dummyIdent(); } - return this.checkLVal(node, binding); + return node; }; lp.toAssignableList = function (exprList, binding) { @@ -527,6 +527,8 @@ lp.parseExprList = function (close, allowEmpty) { return elts; }; +// Okay + },{"..":"/src\\index.js","./parseutil":"/src\\loose\\parseutil.js","./state":"/src\\loose\\state.js"}],"/src\\loose\\index.js":[function(_dereq_,module,exports){ // Acorn: Loose parser // @@ -579,6 +581,7 @@ _dereq_("./statement"); _dereq_("./expression"); exports.LooseParser = _state.LooseParser; +exports.pluginsLoose = _state.pluginsLoose; acorn.defaultOptions.tabSize = 4; @@ -590,6 +593,7 @@ function parse_dammit(input, options) { acorn.parse_dammit = parse_dammit; acorn.LooseParser = _state.LooseParser; +acorn.pluginsLoose = _state.pluginsLoose; },{"..":"/src\\index.js","./expression":"/src\\loose\\expression.js","./state":"/src\\loose\\state.js","./statement":"/src\\loose\\statement.js","./tokenize":"/src\\loose\\tokenize.js"}],"/src\\loose\\parseutil.js":[function(_dereq_,module,exports){ "use strict"; @@ -610,9 +614,14 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons var _ = _dereq_(".."); +// Registered plugins +var pluginsLoose = {}; + +exports.pluginsLoose = pluginsLoose; + var LooseParser = (function () { function LooseParser(input, options) { - _classCallCheck(this, LooseParser); + this.toks = _.tokenizer(input, options); this.options = this.toks.options; @@ -627,6 +636,9 @@ var LooseParser = (function () { this.curIndent = 0; this.curLineStart = 0; this.nextLineStart = this.lineEnd(this.curLineStart) + 1; + // Load plugins + this.options.pluginsLoose = options.pluginsLoose || {}; + this.loadPlugins(this.options.pluginsLoose); } LooseParser.prototype.startNode = function startNode() { @@ -653,10 +665,26 @@ var LooseParser = (function () { return node; }; - LooseParser.prototype.dummyIdent = function dummyIdent() { + LooseParser.prototype.dummyNode = function dummyNode(type) { var dummy = this.startNode(); + dummy.type = type; + dummy.end = dummy.start; + if (this.options.locations) dummy.loc.end = dummy.loc.start; + if (this.options.ranges) dummy.range[1] = dummy.start; + this.last = { type: _.tokTypes.name, start: dummy.start, end: dummy.start, loc: dummy.loc }; + return dummy; + }; + + LooseParser.prototype.dummyIdent = function dummyIdent() { + var dummy = this.dummyNode("Identifier"); dummy.name = "✖"; - return this.finishNode(dummy, "Identifier"); + return dummy; + }; + + LooseParser.prototype.dummyString = function dummyString() { + var dummy = this.dummyNode("Literal"); + dummy.value = dummy.raw = "✖"; + return dummy; }; LooseParser.prototype.eat = function eat(type) { @@ -732,6 +760,18 @@ var LooseParser = (function () { return true; }; + LooseParser.prototype.extend = function extend(name, f) { + this[name] = f(this[name]); + }; + + LooseParser.prototype.loadPlugins = function loadPlugins(pluginConfigs) { + for (var _name in pluginConfigs) { + var plugin = pluginsLoose[_name]; + if (!plugin) throw new Error("Plugin '" + _name + "' not found"); + plugin(this, pluginConfigs[_name]); + } + }; + return LooseParser; })(); @@ -870,7 +910,6 @@ lp.parseStatement = function () { this.expect(_.tokTypes.parenL); clause.param = this.toAssignable(this.parseExprAtom(), true); this.expect(_.tokTypes.parenR); - clause.guard = null; clause.body = this.parseBlock(); node.handler = this.finishNode(clause, "CatchClause"); } @@ -1104,7 +1143,7 @@ lp.parseImport = function () { this.eat(_.tokTypes.comma); } node.specifiers = this.parseImportSpecifierList(); - node.source = this.eatContextual("from") ? this.parseExprAtom() : null; + node.source = this.eatContextual("from") && this.tok.type == _.tokTypes.string ? this.parseExprAtom() : this.dummyString(); if (elt) node.specifiers.unshift(elt); } this.semicolon(); @@ -1128,7 +1167,7 @@ lp.parseImportSpecifierList = function () { while (!this.closes(_.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { var elt = this.startNode(); if (this.eat(_.tokTypes.star)) { - if (this.eatContextual("as")) elt.local = this.parseIdent(); + elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent(); this.finishNode(elt, "ImportNamespaceSpecifier"); } else { if (this.isContextual("from")) break; @@ -1276,5 +1315,4 @@ lp.lookAhead = function (n) { },{"..":"/src\\index.js","./state":"/src\\loose\\state.js"}]},{},["/src\\loose\\index.js"])("/src\\loose\\index.js") }); - -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/node_modules/treehugger/lib/acorn/dist/walk.js b/node_modules/treehugger/lib/acorn/dist/walk.js index c3323266..63360237 100644 --- a/node_modules/treehugger/lib/acorn/dist/walk.js +++ b/node_modules/treehugger/lib/acorn/dist/walk.js @@ -1,4 +1,5 @@ define(["require", "exports", "module", "./acorn"], function(require, exports, module) { + (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}(g.acorn || (g.acorn = {})).walk = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= end)) base[type](node, st, c); - if (test(type, node) && (start == null || node.start == start) && (end == null || node.end == end)) throw new Found(node, st); + if ((start == null || node.start == start) && (end == null || node.end == end) && test(type, node)) throw new Found(node, st); })(node, state); } catch (e) { if (e instanceof Found) return e; @@ -247,20 +248,28 @@ base.FunctionDeclaration = function (node, st, c) { }; base.VariableDeclaration = function (node, st, c) { for (var i = 0; i < node.declarations.length; ++i) { - var decl = node.declarations[i]; - c(decl.id, st, "Pattern"); - if (decl.init) c(decl.init, st, "Expression"); + c(node.declarations[i], st); } }; +base.VariableDeclarator = function (node, st, c) { + c(node.id, st, "Pattern"); + if (node.init) c(node.init, st, "Expression"); +}; base.Function = function (node, st, c) { + if (node.id) c(node.id, st, "Pattern"); for (var i = 0; i < node.params.length; i++) { c(node.params[i], st, "Pattern"); - }c(node.body, st, "ScopeBody"); + }c(node.body, st, node.expression ? "ScopeExpression" : "ScopeBody"); }; +// FIXME drop these node types in next major version +// (They are awkward, and in ES6 every block can be a scope.) base.ScopeBody = function (node, st, c) { return c(node, st, "Statement"); }; +base.ScopeExpression = function (node, st, c) { + return c(node, st, "Expression"); +}; base.Pattern = function (node, st, c) { if (node.type == "Identifier") c(node, st, "VariablePattern");else if (node.type == "MemberExpression") c(node, st, "MemberPattern");else c(node, st); @@ -328,12 +337,16 @@ base.MemberExpression = function (node, st, c) { if (node.computed) c(node.property, st, "Expression"); }; base.ExportNamedDeclaration = base.ExportDefaultDeclaration = function (node, st, c) { - if (node.declaration) c(node.declaration, st); + if (node.declaration) c(node.declaration, st, node.type == "ExportNamedDeclaration" || node.declaration.id ? "Statement" : "Expression"); + if (node.source) c(node.source, st, "Expression"); +}; +base.ExportAllDeclaration = function (node, st, c) { + c(node.source, st, "Expression"); }; base.ImportDeclaration = function (node, st, c) { for (var i = 0; i < node.specifiers.length; i++) { c(node.specifiers[i], st); - } + }c(node.source, st, "Expression"); }; base.ImportSpecifier = base.ImportDefaultSpecifier = base.ImportNamespaceSpecifier = base.Identifier = base.Literal = ignore; diff --git a/node_modules/treehugger/lib/treehugger/js/parse_test.js b/node_modules/treehugger/lib/treehugger/js/parse_test.js index befde189..146fac6b 100644 --- a/node_modules/treehugger/lib/treehugger/js/parse_test.js +++ b/node_modules/treehugger/lib/treehugger/js/parse_test.js @@ -99,12 +99,15 @@ module.exports = { assert.equal(parser.parse("if(").toString(), '[If(Var("✖"),Block([]),None())]'); // todo should this be broken if and a function outside? assert.equal(parser.parse("if(hello.\nfunction hello() { return 0; }").toString(), '[If(PropAccess(Var("hello"),"✖"),Function("hello",[],[Return(Num("0"))]),None())]'); - assert.equal(parser.parse("var\nfunction hello() {}").toString(), '[VarDecls([]),Function("hello",[],[])]'); + // assert.equal(parser.parse("var\nfunction hello() {}").toString(), '[VarDecls([]),Function("hello",[],[])]'); }, "test parse literals": function() { assert.equal(parser.parse("true").toString(), '[Var("true")]'); assert.equal(parser.parse("15").toString(), '[Num("15")]'); assert.equal(parser.parse("15.5").toString(), '[Num("15.5")]'); + }, + "test es7": function() { + assert.equal(parser.parse("async function a(x) {await y()}").toString(), '[Function("a",[FArg("x")],[Call(Var("y"),[])])]'); } }; diff --git a/node_modules/treehugger/package.json b/node_modules/treehugger/package.json index 078782dc..992ca6bb 100644 --- a/node_modules/treehugger/package.json +++ b/node_modules/treehugger/package.json @@ -13,6 +13,10 @@ "url" : "http://github.com/ajaxorg/treehugger.git" }, "engines" : { - "node" : ">= 0.4.0" + "node" : ">= 0.4.0" + }, + "scripts": { + "test": "node lib/treehugger/js/parse_test.js", + "acorn": "node ../acorn/bin/build-acorn.js ; mv ../acorn/dist/* lib/acorn/dist" } } diff --git a/package.json b/package.json index 5009162d..37818e45 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "c9", "description": "New Cloud9 Client", - "version": "3.1.956", + "version": "3.1.1045", "author": "Ajax.org B.V. ", "private": true, "main": "bin/c9", @@ -20,6 +20,7 @@ "engine.io": "1.5.3", "engine.io-client": "1.5.3", "eslint": "git://github.com/cloud9ide/eslint.git#dc500e81162bf0cb4747a4a415c121b0c46975cb", + "jsonm": "1.0.6", "http-error": "~0.0.5", "less": "^2.4.0", "mime": "~1.2.9", @@ -55,23 +56,23 @@ "c9" ], "c9plugins": { - "c9.ide.language": "#b30e79842a", + "c9.ide.language": "#9d12de412d", "c9.ide.language.css": "#be07d72209", "c9.ide.language.generic": "#2b5cc6275e", "c9.ide.language.html": "#9be847c0ce", "c9.ide.language.html.diff": "#24f3608d26", "c9.ide.language.javascript": "#1a0b1584c2", "c9.ide.language.javascript.immediate": "#c8b1e5767a", - "c9.ide.language.javascript.eslint": "#586becb51d", + "c9.ide.language.javascript.eslint": "#d7b067e838", "c9.ide.language.javascript.tern": "#f9ba3813d7", "c9.ide.language.javascript.infer": "#9cf94f77be", - "c9.ide.language.jsonalyzer": "#f0bb823c6f", + "c9.ide.language.jsonalyzer": "#ef0ea1d28f", "c9.ide.collab": "#10c224f9b8", "c9.ide.local": "#a6e689e33b", "c9.ide.find": "#e33fbaed2f", "c9.ide.find.infiles": "#c3bf17286d", "c9.ide.find.replace": "#8cbce45290", - "c9.ide.run.debug": "#3e06ddc0d2", + "c9.ide.run.debug": "#8b77a8379d", "c9.automate": "#47e2c429c9", "c9.ide.ace.emmet": "#6dc4585e02", "c9.ide.ace.gotoline": "#a8ff07c8f4", @@ -90,8 +91,8 @@ "c9.ide.imgeditor": "#612e75ef4f", "c9.ide.immediate": "#a962119bec", "c9.ide.installer": "#0fde9f0067", - "c9.ide.language.python": "#302813a7e3", - "c9.ide.language.go": "#undefined", + "c9.ide.language.python": "#03b2523dc7", + "c9.ide.language.go": "#c1446b259f", "c9.ide.mount": "#915b3d20be", "c9.ide.navigate": "#38ae100ea1", "c9.ide.newresource": "#981a408a7b", diff --git a/plugins/c9.core/ext.js b/plugins/c9.core/ext.js index e6c71bf4..d8a1e866 100644 --- a/plugins/c9.core/ext.js +++ b/plugins/c9.core/ext.js @@ -598,7 +598,7 @@ define(function(require, exports, module) { api[type].get("persistent/" + apiKey, function(err, data){ if (err) return callback(err); - try { callback(null, JSON.stringify(data)); } + try { callback(null, JSON.parse(data)); } catch(e){ return callback(e); } }); } @@ -613,7 +613,11 @@ define(function(require, exports, module) { else if (context == "workspace") type = "project"; else throw new Error("Unsupported context: " + context); - api[type].put("persistent/" + apiKey, { data: JSON.stringify(data) }, callback); + api[type].put("persistent/" + apiKey, { + body: { + data: JSON.stringify(data) + } + }, callback); } /***** Register and define API *****/ diff --git a/plugins/c9.core/util.js b/plugins/c9.core/util.js index 3ce82161..0fdeb788 100644 --- a/plugins/c9.core/util.js +++ b/plugins/c9.core/util.js @@ -57,7 +57,8 @@ define(function(require, exports, module) { "text/x-csharp": "page_white_csharp", "text/x-java-source": "page_white_cup", "text/x-markdown": "page_white_text", - "text/x-xquery": "page_white_code" + "text/x-xquery": "page_white_code", + "text/x-go": "page_white_code", }; var contentTypes = { @@ -87,6 +88,7 @@ define(function(require, exports, module) { "xhtml": "application/xhtml+xml", "coffee": "text/x-script.coffeescript", "py": "text/x-script.python", + "go": "text/x-go", "java": "text/x-java-source", "logic": "text/x-logiql", diff --git a/plugins/c9.ide.browsersupport/browsersupport.js b/plugins/c9.ide.browsersupport/browsersupport.js index ea9c1190..48e6dac9 100644 --- a/plugins/c9.ide.browsersupport/browsersupport.js +++ b/plugins/c9.ide.browsersupport/browsersupport.js @@ -9,6 +9,7 @@ define(function(require, exports, module) { var Plugin = imports.Plugin; require("ace/lib/es5-shim"); + require("ace/lib/es6-shim"); var useragent = require("ace/lib/useragent"); var dom = require("ace/lib/dom"); diff --git a/plugins/c9.ide.dialog.common/error.js b/plugins/c9.ide.dialog.common/error.js index 33e12738..dda62571 100644 --- a/plugins/c9.ide.dialog.common/error.js +++ b/plugins/c9.ide.dialog.common/error.js @@ -122,10 +122,10 @@ define(function(require, exports, module) { metrics.increment("dialog.error"); - errorHandler.log(new Error("Error dialog shown"), { - message: message, - messageString: getMessageString(message), - }); + // errorHandler.log(new Error("Error dialog shown"), { + // message: message, + // messageString: getMessageString(message), + // }); } hide(function() { diff --git a/plugins/c9.ide.plugins/debug.js b/plugins/c9.ide.plugins/debug.js index 1c46a254..cc6d76fb 100644 --- a/plugins/c9.ide.plugins/debug.js +++ b/plugins/c9.ide.plugins/debug.js @@ -45,7 +45,7 @@ define(function(require, exports, module) { var ENABLED = c9.location.indexOf("debug=2") > -1; var HASSDK = ENABLED || experimental.addExperiment("sdk", false, "SDK/Load Custom Plugins"); - var reParts = /^(builders|keymaps|modes|outline|runners|snippets|themes)\/(.*)/; + var reParts = /^(builders|keymaps|modes|outline|runners|snippets|themes|templates)\/(.*)/; var reModule = /(?:_highlight_rules|_test|_worker|_fold|_behaviou?r)\.js$/; var jsExtRe = /\.js$/; diff --git a/plugins/c9.ide.server/plugins.js b/plugins/c9.ide.server/plugins.js index 5922d825..64c2fe89 100644 --- a/plugins/c9.ide.server/plugins.js +++ b/plugins/c9.ide.server/plugins.js @@ -35,6 +35,7 @@ define(function(require, exports, module) { ace_tree: "lib/ace_tree/lib/ace_tree", treehugger: "lib/treehugger/lib/treehugger", acorn: "lib/treehugger/lib/acorn", + jsonm: "lib/jsonm", tern: "lib/tern", tern_from_ts: "lib/tern_from_ts", ui: "lib/ui", @@ -60,6 +61,7 @@ define(function(require, exports, module) { "tern", "tern_from_ts", "treehugger", + "jsonm", "pivottable", "architect", "source-map", diff --git a/plugins/c9.ide.ui/lib_apf.js b/plugins/c9.ide.ui/lib_apf.js index b7b625cc..19d57fcb 100644 --- a/plugins/c9.ide.ui/lib_apf.js +++ b/plugins/c9.ide.ui/lib_apf.js @@ -2988,10 +2988,11 @@ String.prototype.trim = function(){ * @param {Number} times Number of times to repeat the String concatenation * @type {String} */ -String.prototype.repeat = function(times) { - return Array(times + 1).join(this); -}; - +if (!String.prototype.repeat) { + String.prototype.repeat = function(times) { + return Array(times + 1).join(this); + }; +} /* * Count the number of occurences of substring 'str' inside a string * diff --git a/plugins/c9.preview/lib/middleware/sanitize-path-param.js b/plugins/c9.preview/lib/middleware/sanitize-path-param.js new file mode 100644 index 00000000..f3cf8782 --- /dev/null +++ b/plugins/c9.preview/lib/middleware/sanitize-path-param.js @@ -0,0 +1,15 @@ +"use strict"; + +var Path = require("path"); + +module.exports = function sanitzePreviewPath(req, res, next) { + var normalized = Path.normalize(decodeURIComponent(req.params.path)); + + // N.B. Path.normalize does not strip away when the path starts with "../" + if (normalized) + normalized = normalized.replace(/[.]{2}\//g, "") || "/"; + + req.params.path = normalized; + + next(); +}; diff --git a/plugins/c9.preview/lib/middleware/sanitize-path-param_test.js b/plugins/c9.preview/lib/middleware/sanitize-path-param_test.js new file mode 100644 index 00000000..6120a020 --- /dev/null +++ b/plugins/c9.preview/lib/middleware/sanitize-path-param_test.js @@ -0,0 +1,60 @@ +"use struct"; +"use server"; + +require("c9/inline-mocha")(module); + +var sanitize = require("./sanitize-path-param"); +var async = require("async"); +var format = require("util").format; +var assert = require("assert"); + +describe(__filename, function() { + it("should sanitize params", function(done) { + + //https://preview.new-mvhenten.c9.io/mvhenten/demo-project/%2e%2e/foo.txt + + + var cases = [{ + path: "%2e%2e/foo.txt", + expect: "foo.txt" + }, { + path: "%2e%2e/%2e%2e/foo.txt", + expect: "foo.txt" + }, { + path: "%2e%2e/%2e%2e/%2e%2e/foo.txt", + expect: "foo.txt" + }, { + path: "foo/bar/%2e%2e/%2e%2e/xoo.txt", + expect: "xoo.txt" + }, { + path: "../foo.txt", + expect: "foo.txt" + }, { + path: "foo/../../foo.txt", + expect: "foo.txt" + }, { + path: "%7E/foo/../../foo.txt", + expect: "foo.txt" + }, { + path: "~/foo.txt", + expect: "~/foo.txt" + }, { + path: "%7E/../foo.txt", + expect: "foo.txt" + }]; + + + async.each(cases, function(testCase, next) { + var mockReq = { + params: { + path: testCase.path + } + }; + + sanitize(mockReq, null, function() { + assert.equal(mockReq.params.path, testCase.expect, format("Expect %s to become %s", testCase.path, testCase.expect)); + next(); + }); + }, done); + }); +}); diff --git a/plugins/c9.preview/preview.js b/plugins/c9.preview/preview.js index 853a33e7..0f2c1a98 100644 --- a/plugins/c9.preview/preview.js +++ b/plugins/c9.preview/preview.js @@ -21,6 +21,7 @@ define(function(require, exports, module) { var userContent = imports["user-content.redirect"]; var getVfsServers = imports["vfs.serverlist"].getServers; + var frontdoor = require("frontdoor"); var error = require("http-error"); var requestTimeout = require("c9/request_timeout"); @@ -50,6 +51,7 @@ define(function(require, exports, module) { } }, [ requestTimeout(15*60*1000), + require("./lib/middleware/sanitize-path-param"), handler.getProjectSession(), handler.getRole(db), handler.getProxyUrl(function() { diff --git a/plugins/c9.preview/views/progress.html.ejs b/plugins/c9.preview/views/progress.html.ejs index a7947afc..0e0396e9 100644 --- a/plugins/c9.preview/views/progress.html.ejs +++ b/plugins/c9.preview/views/progress.html.ejs @@ -1,9 +1,6 @@ - - + <%=title%> @@ -20,11 +17,9 @@ Home diff --git a/plugins/c9.static/build.js b/plugins/c9.static/build.js index 3965388d..756d9f67 100644 --- a/plugins/c9.static/build.js +++ b/plugins/c9.static/build.js @@ -267,6 +267,7 @@ function main(options, imports, register) { "plugins/c9.ide.language.python/worker/python_linter", "plugins/c9.ide.language.python/worker/python_completer", "plugins/c9.ide.language.python/worker/python_jsonalyzer", + "plugins/c9.ide.language.go/worker/go_completer", "plugins/c9.ide.language.html/html_completer", "plugins/c9.ide.language.css/css_handler", "plugins/c9.ide.language.javascript.tern/worker/tern_worker", diff --git a/plugins/c9.vfs.standalone/standalone.js b/plugins/c9.vfs.standalone/standalone.js index 06ab4a35..cd2019e7 100644 --- a/plugins/c9.vfs.standalone/standalone.js +++ b/plugins/c9.vfs.standalone/standalone.js @@ -183,7 +183,6 @@ function plugin(options, imports, register) { api.get("/configs/require_config.js", function(req, res, next) { var config = res.getOptions().requirejsConfig || {}; - config.waitSeconds = 240; res.writeHead(200, {"Content-Type": "application/javascript"}); res.end("requirejs.config(" + JSON.stringify(config) + ");"); @@ -212,6 +211,54 @@ function plugin(options, imports, register) { api.get("/api.json", {name: "api"}, frontdoor.middleware.describeApi(api)); + api.get("/api/project/:pid/persistent/:apikey", { + params: { + pid: { type: "number" }, + apikey: { type: "string" } + } + }, persistentDataApiMock); + api.put("/api/project/:pid/persistent/:apikey", { + params: { + data: { type: "string", source: "body" }, + pid: { type: "number" }, + apikey: { type: "string" }, + } + }, persistentDataApiMock); + api.get("/api/user/persistent/:apikey", { + params: { + apikey: { type: "string" } + } + }, persistentDataApiMock); + api.put("/api/user/persistent/:apikey", { + params: { + data: { type: "string", source: "body" }, + apikey: { type: "string" }, + } + }, persistentDataApiMock); + + function persistentDataApiMock(req, res, next) { + var name = (req.params.pid || 0) + "-" + req.params.apikey; + var data = req.params.data; + console.log(name, data) + if (/[^\w+=\-]/.test(name)) + return next(new Error("Invalid apikey")); + var path = join(options.installPath, ".c9", "persistent"); + var method = req.method.toLowerCase() + if (method == "get") { + res.writeHead(200, {"Content-Type": "application/octet-stream"}); + var stream = fs.createReadStream(path + "/" + name); + stream.pipe(res); + } else if (method == "put") { + require("mkdirp")(path, function(e) { + fs.writeFile(path + "/" + name, data, "", function(err) { + if (err) return next(err); + res.writeHead(200, {"Content-Type": "application/octet-stream"}); + res.end(""); + }); + }); + } + } + // fake authentication api.authenticate = api.authenticate || function() { return function(req, res, next) { diff --git a/plugins/c9.vfs.standalone/views/standalone.html.ejs b/plugins/c9.vfs.standalone/views/standalone.html.ejs index c9f04bbe..cfdfbe85 100644 --- a/plugins/c9.vfs.standalone/views/standalone.html.ejs +++ b/plugins/c9.vfs.standalone/views/standalone.html.ejs @@ -2,13 +2,7 @@ - - Cloud9 - <% } %>