Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V8intrinsic syntax plugin #10148

Merged
merged 13 commits into from Sep 6, 2019
5 changes: 5 additions & 0 deletions packages/babel-generator/src/generators/expressions.js
Expand Up @@ -264,3 +264,8 @@ export function PrivateName(node: Object) {
this.token("#");
this.print(node.id, node);
}

export function V8IntrinsicIdentifier(node: Object) {
this.token("%");
this.word(node.name);
}
@@ -0,0 +1 @@
%DebugPrint(foo);
@@ -0,0 +1,3 @@
{
"plugins": ["v8intrinsic"]
}
@@ -0,0 +1 @@
%DebugPrint(foo);
2 changes: 1 addition & 1 deletion packages/babel-parser/src/parser/expression.js
Expand Up @@ -2191,7 +2191,7 @@ export default class ExpressionParser extends LValParser {
if (
this.match(tt.semi) ||
(!this.match(tt.star) && !this.state.type.startsExpr) ||
this.canInsertSemicolon()
this.hasPrecedingLineBreak()
) {
node.delegate = false;
node.argument = null;
Expand Down
6 changes: 6 additions & 0 deletions packages/babel-parser/src/plugin-utils.js
Expand Up @@ -69,6 +69,10 @@ export function validatePlugins(plugins: PluginList) {
throw new Error("Cannot combine flow and typescript plugins.");
}

if (hasPlugin(plugins, "placeholders") && hasPlugin(plugins, "v8intrinsic")) {
throw new Error("Cannot combine placeholders and v8intrinsic plugins.");
}

if (
hasPlugin(plugins, "pipelineOperator") &&
!PIPELINE_PROPOSALS.includes(
Expand All @@ -89,13 +93,15 @@ import flow from "./plugins/flow";
import jsx from "./plugins/jsx";
import typescript from "./plugins/typescript";
import placeholders from "./plugins/placeholders";
import v8intrinsic from "./plugins/v8intrinsic";

// NOTE: order is important. estree must come first; placeholders must come last.
export const mixinPlugins: { [name: string]: MixinPlugin } = {
estree,
jsx,
flow,
typescript,
v8intrinsic,
placeholders,
};

Expand Down
32 changes: 32 additions & 0 deletions packages/babel-parser/src/plugins/v8intrinsic.js
@@ -0,0 +1,32 @@
import type Parser from "../parser";
import { types as tt } from "../tokenizer/types";
import * as N from "../types";

export default (superClass: Class<Parser>): Class<Parser> =>
class extends superClass {
parseV8Intrinsic(): N.Expression {
if (this.match(tt.modulo)) {
const v8IntrinsicStart = this.state.start;
// let the `loc` of Identifier starts from `%`
const node = this.startNode();
this.eat(tt.modulo);
if (this.match(tt.name)) {
const name = this.parseIdentifierName(this.state.start);
const identifier = this.createIdentifier(node, name);
identifier.type = "V8IntrinsicIdentifier";
if (this.match(tt.parenL)) {
return identifier;
}
}
this.unexpected(v8IntrinsicStart);
}
}

/* ============================================================ *
* parser/expression.js *
* ============================================================ */

parseExprAtom(): N.Expression {
return this.parseV8Intrinsic() || super.parseExprAtom(...arguments);
}
};
3 changes: 2 additions & 1 deletion packages/babel-parser/src/tokenizer/types.js
Expand Up @@ -148,7 +148,8 @@ export const types: { [name: string]: TokenType } = {
relational: createBinop("</>/<=/>=", 8),
bitShift: createBinop("<</>>/>>>", 9),
plusMin: new TokenType("+/-", { beforeExpr, binop: 10, prefix, startsExpr }),
modulo: createBinop("%", 11),
// startsExpr: required by v8intrinsic plugin
modulo: new TokenType("%", { beforeExpr, binop: 11, startsExpr }),
star: createBinop("*", 11),
slash: createBinop("/", 11),
exponent: new TokenType("**", {
Expand Down
@@ -0,0 +1 @@
::%DebugPrint(null)
@@ -0,0 +1,6 @@
{
"plugins": [
"v8intrinsic"
],
"throws": "Unexpected token (1:0)"
}
@@ -0,0 +1 @@
a.%DebugPrint();
@@ -0,0 +1,6 @@
{
"plugins": [
"v8intrinsic"
],
"throws": "Unexpected token (1:2)"
}
@@ -0,0 +1 @@
%DebugPrint(foo)
@@ -0,0 +1,4 @@
{
"plugins": [],
"throws": "Unexpected token (1:0)"
}
@@ -0,0 +1,2 @@
const i = %DebugPrint;
i(foo);
@@ -0,0 +1,4 @@
{
"plugins": ["v8intrinsic"],
"throws": "Unexpected token (1:10)"
}
@@ -0,0 +1 @@
%DebugPrint?.(null)
@@ -0,0 +1,7 @@
{
"plugins": [
"optionalChaining",
"v8intrinsic"
],
"throws": "Unexpected token (1:0)"
}
@@ -0,0 +1 @@
async () => { await %StringParseInt("42", 10) }
JLHwung marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1,191 @@
{
"type": "File",
"start": 0,
"end": 47,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 47
}
},
"program": {
"type": "Program",
"start": 0,
"end": 47,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 47
}
},
"sourceType": "script",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start": 0,
"end": 47,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 47
}
},
"expression": {
"type": "ArrowFunctionExpression",
"start": 0,
"end": 47,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 1,
"column": 47
}
},
"id": null,
"generator": false,
"async": true,
"params": [],
"body": {
"type": "BlockStatement",
"start": 12,
"end": 47,
"loc": {
"start": {
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 47
}
},
"body": [
{
"type": "ExpressionStatement",
"start": 14,
"end": 45,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 1,
"column": 45
}
},
"expression": {
"type": "AwaitExpression",
"start": 14,
"end": 45,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 1,
"column": 45
}
},
"argument": {
"type": "CallExpression",
"start": 20,
"end": 45,
"loc": {
"start": {
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 45
}
},
"callee": {
"type": "V8IntrinsicIdentifier",
"start": 20,
"end": 35,
"loc": {
"start": {
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 35
},
"identifierName": "StringParseInt"
},
"name": "StringParseInt"
},
"arguments": [
{
"type": "StringLiteral",
"start": 36,
"end": 40,
"loc": {
"start": {
"line": 1,
"column": 36
},
"end": {
"line": 1,
"column": 40
}
},
"extra": {
"rawValue": "42",
"raw": "\"42\""
},
"value": "42"
},
{
"type": "NumericLiteral",
"start": 42,
"end": 44,
"loc": {
"start": {
"line": 1,
"column": 42
},
"end": {
"line": 1,
"column": 44
}
},
"extra": {
"rawValue": 10,
"raw": "10"
},
"value": 10
}
]
}
}
}
],
"directives": []
}
}
}
],
"directives": []
}
}
@@ -0,0 +1 @@
%DebugPrint(foo)