diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index d547ebcec5..fcc2ad23a9 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -3,8 +3,13 @@ import * as N from "../types"; import { types as tt, type TokenType } from "../tokenizer/types"; import ExpressionParser from "./expression"; -import { isIdentifierChar } from "../util/identifier"; +import { + isIdentifierChar, + isIdentifierStart, + keywordRelationalOperator, +} from "../util/identifier"; import { lineBreak, skipWhiteSpace } from "../util/whitespace"; +import * as charCodes from "charcodes"; // Reused empty array added for node fields that are always empty. @@ -71,6 +76,33 @@ export default class StatementParser extends ExpressionParser { return this.finishNode(node, "InterpreterDirective"); } + isLet() { + if (!this.isContextual("let")) { + return false; + } + skipWhiteSpace.lastIndex = this.state.pos; + const skip = skipWhiteSpace.exec(this.state.input); + // $FlowIgnore + const next = this.state.pos + skip[0].length; + const nextCh = this.state.input.charCodeAt(next); + if ( + (nextCh === charCodes.leftCurlyBrace && + !lineBreak.test(this.state.input.slice(this.state.end, next))) || + nextCh === charCodes.leftSquareBracket + ) { + return true; + } + if (isIdentifierStart(nextCh)) { + let pos = next + 1; + while (isIdentifierChar(this.state.input.charCodeAt(pos))) { + ++pos; + } + const ident = this.state.input.slice(next, pos); + if (!keywordRelationalOperator.test(ident)) return true; + } + return false; + } + // Parse a single statement. // // If expecting a statement and finding a slash operator, parse a @@ -86,8 +118,14 @@ export default class StatementParser extends ExpressionParser { } parseStatementContent(declaration: boolean, topLevel: ?boolean): N.Statement { - const starttype = this.state.type; + let starttype = this.state.type; const node = this.startNode(); + let kind; + + if (this.isLet()) { + starttype = tt._var; + kind = "let"; + } // Most types of statements are recognized by the keyword they // start with. Many are trivial to parse, some require a bit of @@ -129,12 +167,11 @@ export default class StatementParser extends ExpressionParser { case tt._try: return this.parseTryStatement(node); - case tt._let: case tt._const: - if (!declaration) this.unexpected(); // NOTE: falls through to _var - case tt._var: - return this.parseVarStatement(node, starttype); + kind = kind || this.state.value; + if (!declaration && kind !== "var") this.unexpected(); + return this.parseVarStatement(node, kind); case tt._while: return this.parseWhileStatement(node); @@ -424,18 +461,19 @@ export default class StatementParser extends ExpressionParser { return this.parseFor(node, null); } - if (this.match(tt._var) || this.match(tt._let) || this.match(tt._const)) { + const isLet = this.isLet(); + if (this.match(tt._var) || this.match(tt._const) || isLet) { const init = this.startNode(); - const varKind = this.state.type; + const kind = isLet ? "let" : this.state.value; this.next(); - this.parseVar(init, true, varKind); + this.parseVar(init, true, kind); this.finishNode(init, "VariableDeclaration"); if (this.match(tt._in) || this.isContextual("of")) { if (init.declarations.length === 1) { const declaration = init.declarations[0]; const isForInInitializer = - varKind === tt._var && + kind === "var" && declaration.init && declaration.id.type != "ObjectPattern" && declaration.id.type != "ArrayPattern" && @@ -606,7 +644,7 @@ export default class StatementParser extends ExpressionParser { parseVarStatement( node: N.VariableDeclaration, - kind: TokenType, + kind: "var" | "let" | "const", ): N.VariableDeclaration { this.next(); this.parseVar(node, false, kind); @@ -862,12 +900,11 @@ export default class StatementParser extends ExpressionParser { parseVar( node: N.VariableDeclaration, isFor: boolean, - kind: TokenType, + kind: "var" | "let" | "const", ): N.VariableDeclaration { const declarations = (node.declarations = []); const isTypescript = this.hasPlugin("typescript"); - // $FlowFixMe - node.kind = kind.keyword; + node.kind = kind; for (;;) { const decl = this.startNode(); this.parseVarHead(decl); @@ -875,7 +912,7 @@ export default class StatementParser extends ExpressionParser { decl.init = this.parseMaybeAssign(isFor); } else { if ( - kind === tt._const && + kind === "const" && !(this.match(tt._in) || this.isContextual("of")) ) { // `const` with no initializer is allowed in TypeScript. @@ -1638,11 +1675,7 @@ export default class StatementParser extends ExpressionParser { } this.parseDecorators(false); return this.parseClass(expr, true, true); - } else if ( - this.match(tt._let) || - this.match(tt._const) || - this.match(tt._var) - ) { + } else if (this.match(tt._const) || this.match(tt._var) || this.isLet()) { return this.raise( this.state.start, "Only expressions, functions or classes are allowed as the `default` export.", @@ -1661,7 +1694,7 @@ export default class StatementParser extends ExpressionParser { isExportDefaultSpecifier(): boolean { if (this.match(tt.name)) { - return this.state.value !== "async"; + return this.state.value !== "async" && this.state.value !== "let"; } if (!this.match(tt._default)) { @@ -1710,9 +1743,9 @@ export default class StatementParser extends ExpressionParser { return ( this.state.type.keyword === "var" || this.state.type.keyword === "const" || - this.state.type.keyword === "let" || this.state.type.keyword === "function" || this.state.type.keyword === "class" || + this.isLet() || this.isAsyncFunction() ); } diff --git a/packages/babel-parser/src/plugins/flow.js b/packages/babel-parser/src/plugins/flow.js index 0dbab81e3a..e45ddd6b29 100644 --- a/packages/babel-parser/src/plugins/flow.js +++ b/packages/babel-parser/src/plugins/flow.js @@ -344,7 +344,7 @@ export default (superClass: Class): Class => } else { if ( this.match(tt._const) || - this.match(tt._let) || + this.isLet() || ((this.isContextual("type") || this.isContextual("interface")) && !insideModule) ) { diff --git a/packages/babel-parser/src/plugins/typescript.js b/packages/babel-parser/src/plugins/typescript.js index 0a7c527dfa..80e74859c4 100644 --- a/packages/babel-parser/src/plugins/typescript.js +++ b/packages/babel-parser/src/plugins/typescript.js @@ -1190,8 +1190,15 @@ export default (superClass: Class): Class => if (this.isLineTerminator()) { return; } + let starttype = this.state.type; + let kind; - switch (this.state.type) { + if (this.isContextual("let")) { + starttype = tt._var; + kind = "let"; + } + + switch (starttype) { case tt._function: this.next(); return this.parseFunction(nany, /* isStatement */ true); @@ -1210,8 +1217,8 @@ export default (superClass: Class): Class => } // falls through case tt._var: - case tt._let: - return this.parseVarStatement(nany, this.state.type); + kind = kind || this.state.value; + return this.parseVarStatement(nany, kind); case tt.name: { const value = this.state.value; if (value === "global") { diff --git a/packages/babel-parser/src/tokenizer/index.js b/packages/babel-parser/src/tokenizer/index.js index d527c96913..b3ef098539 100644 --- a/packages/babel-parser/src/tokenizer/index.js +++ b/packages/babel-parser/src/tokenizer/index.js @@ -1384,8 +1384,8 @@ export default class Tokenizer extends LocationParser { if ( prevType === tt._var || - prevType === tt._let || - prevType === tt._const + prevType === tt._const || + prevType === tt.name ) { return false; } diff --git a/packages/babel-parser/src/tokenizer/types.js b/packages/babel-parser/src/tokenizer/types.js index 4d88ed0e11..07a85c30db 100644 --- a/packages/babel-parser/src/tokenizer/types.js +++ b/packages/babel-parser/src/tokenizer/types.js @@ -180,7 +180,6 @@ export const keywords = Object.create(null, { throw: makeKeywordProps("throw", { beforeExpr, prefix, startsExpr }), try: makeKeywordProps("try"), var: makeKeywordProps("var"), - let: makeKeywordProps("let"), const: makeKeywordProps("const"), while: makeKeywordProps("while", { isLoop }), with: makeKeywordProps("with"), diff --git a/packages/babel-parser/src/util/identifier.js b/packages/babel-parser/src/util/identifier.js index 847a61f878..631f9d0394 100644 --- a/packages/babel-parser/src/util/identifier.js +++ b/packages/babel-parser/src/util/identifier.js @@ -57,7 +57,6 @@ const keywords = new Set([ "new", "in", "this", - "let", "const", "class", "extends", @@ -71,6 +70,8 @@ export function isKeyword(word: string): boolean { return keywords.has(word); } +export const keywordRelationalOperator = /^in(stanceof)?$/; + // ## Character categories // Big ugly regular expressions that matches characters in the diff --git a/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-1/input.js b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-1/input.js new file mode 100644 index 0000000000..2b8952b973 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-1/input.js @@ -0,0 +1 @@ +let + 1 diff --git a/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-1/output.json b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-1/output.json new file mode 100644 index 0000000000..d5896aa4d5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-1/output.json @@ -0,0 +1,103 @@ +{ + "type": "File", + "start": 0, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 7 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 7 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 7 + } + }, + "expression": { + "type": "BinaryExpression", + "start": 0, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 7 + } + }, + "left": { + "type": "Identifier", + "start": 0, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + }, + "identifierName": "let" + }, + "name": "let" + }, + "operator": "+", + "right": { + "type": "NumericLiteral", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-2/input.js b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-2/input.js new file mode 100644 index 0000000000..15ea1476df --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-2/input.js @@ -0,0 +1 @@ +var let = 1 diff --git a/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-2/output.json b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-2/output.json new file mode 100644 index 0000000000..dc261c3dcb --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-2/output.json @@ -0,0 +1,105 @@ +{ + "type": "File", + "start": 0, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start": 0, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 4, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "id": { + "type": "Identifier", + "start": 4, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 7 + }, + "identifierName": "let" + }, + "name": "let" + }, + "init": { + "type": "NumericLiteral", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + } + } + ], + "kind": "var" + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-3/input.js b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-3/input.js new file mode 100644 index 0000000000..bf4301ea13 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-3/input.js @@ -0,0 +1 @@ +let instanceof Foo diff --git a/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-3/output.json b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-3/output.json new file mode 100644 index 0000000000..b0f5399086 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-3/output.json @@ -0,0 +1,100 @@ +{ + "type": "File", + "start": 0, + "end": 18, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 18 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 18, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 18 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 18, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 18 + } + }, + "expression": { + "type": "BinaryExpression", + "start": 0, + "end": 18, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 18 + } + }, + "left": { + "type": "Identifier", + "start": 0, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + }, + "identifierName": "let" + }, + "name": "let" + }, + "operator": "instanceof", + "right": { + "type": "Identifier", + "start": 15, + "end": 18, + "loc": { + "start": { + "line": 1, + "column": 15 + }, + "end": { + "line": 1, + "column": 18 + }, + "identifierName": "Foo" + }, + "name": "Foo" + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-4/input.js b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-4/input.js new file mode 100644 index 0000000000..8b1ded17c0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-4/input.js @@ -0,0 +1 @@ +let in {} diff --git a/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-4/output.json b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-4/output.json new file mode 100644 index 0000000000..96851ba7aa --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-4/output.json @@ -0,0 +1,99 @@ +{ + "type": "File", + "start": 0, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "expression": { + "type": "BinaryExpression", + "start": 0, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "left": { + "type": "Identifier", + "start": 0, + "end": 3, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 3 + }, + "identifierName": "let" + }, + "name": "let" + }, + "operator": "in", + "right": { + "type": "ObjectExpression", + "start": 7, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "properties": [] + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-5/input.js b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-5/input.js new file mode 100644 index 0000000000..5ddea3e168 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-5/input.js @@ -0,0 +1,2 @@ +if (1) let +{} diff --git a/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-5/output.json b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-5/output.json new file mode 100644 index 0000000000..ade78031a6 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-5/output.json @@ -0,0 +1,120 @@ +{ + "type": "File", + "start": 0, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "IfStatement", + "start": 0, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "test": { + "type": "NumericLiteral", + "start": 4, + "end": 5, + "loc": { + "start": { + "line": 1, + "column": 4 + }, + "end": { + "line": 1, + "column": 5 + } + }, + "extra": { + "rawValue": 1, + "raw": "1" + }, + "value": 1 + }, + "consequent": { + "type": "ExpressionStatement", + "start": 7, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "expression": { + "type": "Identifier", + "start": 7, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 10 + }, + "identifierName": "let" + }, + "name": "let" + } + }, + "alternate": null + }, + { + "type": "BlockStatement", + "start": 11, + "end": 13, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "body": [], + "directives": [] + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-strict-fail/input.js b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-strict-fail/input.js new file mode 100644 index 0000000000..dc734683c9 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-strict-fail/input.js @@ -0,0 +1,2 @@ +"use strict"; +let + 1 diff --git a/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-strict-fail/options.json b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-strict-fail/options.json new file mode 100644 index 0000000000..8773675903 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/let/let-as-identifier-strict-fail/options.json @@ -0,0 +1,3 @@ +{ + "throws": "let is a reserved word in strict mode (2:0)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0232/options.json b/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0232/options.json index 9fa1302689..81e5594d82 100644 --- a/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0232/options.json +++ b/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0232/options.json @@ -1,3 +1,3 @@ { - "throws": "Unexpected token (1:37)" + "throws": "let is a reserved word in strict mode (1:37)" } diff --git a/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0238/input.js b/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0238/input.js deleted file mode 100644 index c87b8eaaf4..0000000000 --- a/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0238/input.js +++ /dev/null @@ -1 +0,0 @@ -var let diff --git a/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0238/options.json b/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0238/options.json deleted file mode 100644 index 27a7b64d71..0000000000 --- a/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0238/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "throws": "Unexpected token (1:4)" -} diff --git a/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0253/input.js b/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0253/input.js deleted file mode 100644 index 564a1caa1c..0000000000 --- a/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0253/input.js +++ /dev/null @@ -1 +0,0 @@ -let diff --git a/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0253/options.json b/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0253/options.json deleted file mode 100644 index 05dbd26b33..0000000000 --- a/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0253/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "throws": "Unexpected token (1:3)" -} diff --git a/packages/babel-parser/test/unit/util/identifier.js b/packages/babel-parser/test/unit/util/identifier.js index a0d6bb16d2..420971a577 100644 --- a/packages/babel-parser/test/unit/util/identifier.js +++ b/packages/babel-parser/test/unit/util/identifier.js @@ -1,18 +1,42 @@ -import { isKeyword } from "../../../src/util/identifier"; +import { + isKeyword, + keywordRelationalOperator, +} from "../../../src/util/identifier"; describe("identifier", () => { describe("isKeyword", () => { it("break is a keyword", () => { expect(isKeyword("break")).toBe(true); }); - it("let is a keyword", () => { - expect(isKeyword("let")).toBe(true); + it("const is a keyword", () => { + expect(isKeyword("const")).toBe(true); }); it("super is a keyword", () => { expect(isKeyword("super")).toBe(true); }); + it("let is not a keyword", () => { + expect(isKeyword("let")).toBe(false); + }); it("abc is not a keyword", () => { expect(isKeyword("abc")).toBe(false); }); }); + + describe("keywordRelationalOperator", () => { + it("in is true", () => { + expect(keywordRelationalOperator.test("in")).toBe(true); + }); + it("instanceof is true", () => { + expect(keywordRelationalOperator.test("instanceof")).toBe(true); + }); + it("stanceof is false", () => { + expect(keywordRelationalOperator.test("stanceof")).toBe(false); + }); + it("instance is false", () => { + expect(keywordRelationalOperator.test("instance")).toBe(false); + }); + it("abc is false", () => { + expect(keywordRelationalOperator.test("abc")).toBe(false); + }); + }); });