diff --git a/README.md b/README.md index 7013566608..69d83a6af9 100644 --- a/README.md +++ b/README.md @@ -71,3 +71,4 @@ require("babylon").parse("code", { - `exportExtensions` - `exponentiationOperator` - `asyncGenerators` + - `functionSent` diff --git a/src/parser/expression.js b/src/parser/expression.js index 784eb3a3ea..64b7f1c18d 100644 --- a/src/parser/expression.js +++ b/src/parser/expression.js @@ -28,7 +28,7 @@ const pp = Parser.prototype; // strict mode, init properties are also not allowed to be repeated. pp.checkPropClash = function (prop, propHash) { - if (prop.computed || prop.method) return; + if (prop.computed) return; let key = prop.key; let name; @@ -459,9 +459,7 @@ pp.parseExprAtom = function (refShorthandDefaultPos) { return this.parseObj(false, refShorthandDefaultPos); case tt._function: - node = this.startNode(); - this.next(); - return this.parseFunction(node, false); + return this.parseFunctionExpression(); case tt.at: this.parseDecorators(); @@ -493,6 +491,27 @@ pp.parseExprAtom = function (refShorthandDefaultPos) { } }; +pp.parseFunctionExpression = function () { + let node = this.startNode(); + let meta = this.parseIdentifier(true); + if (this.state.inGenerator && this.eat(tt.dot) && this.hasPlugin("functionSent")) { + return this.parseMetaProperty(node, meta, "sent"); + } else { + return this.parseFunction(node, false); + } +}; + +pp.parseMetaProperty = function (node, meta, propertyName) { + node.meta = meta; + node.property = this.parseIdentifier(true); + + if (node.property.name !== propertyName) { + this.raise(node.property.start, `The only valid meta property for new is ${meta.name}.${propertyName}`); + } + + return this.finishNode(node, "MetaProperty"); +}; + pp.parseLiteral = function (value, type) { let node = this.startNode(); this.addExtra(node, "rawValue", value); @@ -592,14 +611,7 @@ pp.parseNew = function () { let meta = this.parseIdentifier(true); if (this.eat(tt.dot)) { - node.meta = meta; - node.property = this.parseIdentifier(true); - - if (node.property.name !== "target") { - this.raise(node.property.start, "The only valid meta property for new is new.target"); - } - - return this.finishNode(node, "MetaProperty"); + return this.parseMetaProperty(node, meta, "target"); } node.callee = this.parseNoCallExpr(); diff --git a/test/fixtures/experimental/function-sent/inside-function/actual.js b/test/fixtures/experimental/function-sent/inside-function/actual.js new file mode 100644 index 0000000000..203379b698 --- /dev/null +++ b/test/fixtures/experimental/function-sent/inside-function/actual.js @@ -0,0 +1,3 @@ +function foo() { + return function.sent; +} diff --git a/test/fixtures/experimental/function-sent/inside-function/options.json b/test/fixtures/experimental/function-sent/inside-function/options.json new file mode 100644 index 0000000000..43a82ec8a1 --- /dev/null +++ b/test/fixtures/experimental/function-sent/inside-function/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Unexpected token (2:17)" +} diff --git a/test/fixtures/experimental/function-sent/inside-generator/actual.js b/test/fixtures/experimental/function-sent/inside-generator/actual.js new file mode 100644 index 0000000000..28760b261b --- /dev/null +++ b/test/fixtures/experimental/function-sent/inside-generator/actual.js @@ -0,0 +1,3 @@ +function* foo() { + return function.sent; +} diff --git a/test/fixtures/experimental/function-sent/inside-generator/expected.json b/test/fixtures/experimental/function-sent/inside-generator/expected.json new file mode 100644 index 0000000000..c0692c9a9d --- /dev/null +++ b/test/fixtures/experimental/function-sent/inside-generator/expected.json @@ -0,0 +1,148 @@ +{ + "type": "File", + "start": 0, + "end": 43, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 43, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "sourceType": "script", + "body": [ + { + "type": "FunctionDeclaration", + "start": 0, + "end": 43, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "id": { + "type": "Identifier", + "start": 10, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "name": "foo" + }, + "generator": true, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 16, + "end": 43, + "loc": { + "start": { + "line": 1, + "column": 16 + }, + "end": { + "line": 3, + "column": 1 + } + }, + "body": [ + { + "type": "ReturnStatement", + "start": 20, + "end": 41, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 23 + } + }, + "argument": { + "type": "MetaProperty", + "start": 27, + "end": 40, + "loc": { + "start": { + "line": 2, + "column": 9 + }, + "end": { + "line": 2, + "column": 22 + } + }, + "meta": { + "type": "Identifier", + "start": 27, + "end": 35, + "loc": { + "start": { + "line": 2, + "column": 9 + }, + "end": { + "line": 2, + "column": 17 + } + }, + "name": "function" + }, + "property": { + "type": "Identifier", + "start": 36, + "end": 40, + "loc": { + "start": { + "line": 2, + "column": 18 + }, + "end": { + "line": 2, + "column": 22 + } + }, + "name": "sent" + } + } + } + ], + "directives": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/function-sent/options.json b/test/fixtures/experimental/function-sent/options.json new file mode 100644 index 0000000000..fea46c76c3 --- /dev/null +++ b/test/fixtures/experimental/function-sent/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["functionSent"] +}