From 7a79b34e6dd098a87f98bfab64c707a640c55ade Mon Sep 17 00:00:00 2001 From: wessberg Date: Sun, 10 Nov 2019 00:40:35 +0100 Subject: [PATCH] feat(optional chaining): add support for optional chaining and nullish coalescing --- documentation/asset/logo-social-preview.png | Bin 0 -> 37811 bytes package.json | 204 +++++++++--------- .../evaluator/evaluate-binary-expression.ts | 4 + .../evaluator/evaluate-call-expression.ts | 7 +- .../evaluate-element-access-expression.ts | 6 +- .../evaluate-property-access-expression.ts | 6 +- .../nullish-coalescing.test.ts | 20 ++ .../optional-chaining.test.ts | 56 +++++ 8 files changed, 198 insertions(+), 105 deletions(-) create mode 100644 documentation/asset/logo-social-preview.png create mode 100644 test/nullish-coalescing/nullish-coalescing.test.ts create mode 100644 test/optional-chaining/optional-chaining.test.ts diff --git a/documentation/asset/logo-social-preview.png b/documentation/asset/logo-social-preview.png new file mode 100644 index 0000000000000000000000000000000000000000..025b8a036248a2f8630db33c97d18d8480c1236c GIT binary patch literal 37811 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 literal 0 HcmV?d00001 diff --git a/package.json b/package.json index f00d8d6..b7001dc 100644 --- a/package.json +++ b/package.json @@ -1,102 +1,106 @@ { - "name": "@wessberg/ts-evaluator", - "version": "0.0.23", - "description": "An interpreter for Typescript that can evaluate an arbitrary Node within a Typescript AST", - "scripts": { - "generate:readme": "scaffold readme --yes", - "generate:license": "scaffold license --yes", - "generate:contributing": "scaffold contributing --yes", - "generate:coc": "scaffold coc --yes", - "generate:changelog": "standard-changelog --first-release", - "generate:all": "npm run generate:license & npm run generate:contributing & npm run generate:coc & npm run generate:readme && npm run generate:changelog", - "clean": "rm -rf dist", - "lint": "tsc --noEmit && tslint -c tslint.json --project tsconfig.json", - "prettier": "prettier --write '{src,test,documentation}/**/*.{js,ts,json,html,xml,css,md}'", - "test": "ava", - "prebuild": "npm run clean", - "build": "npm run rollup", - "rollup": "rollup -c rollup.config.js", - "preversion": "npm run lint && NODE_ENV=production npm run build", - "version": "npm run generate:all && git add .", - "release": "np --no-cleanup --no-yarn" - }, - "keywords": [ - "typescript", - "ts", - "interpreter", - "evaluate", - "evaluator", - "ast" - ], - "files": [ - "dist/**/*.*" - ], - "contributors": [ - { - "name": "Frederik Wessberg", - "email": "frederikwessberg@hotmail.com", - "url": "https://github.com/wessberg", - "imageUrl": "https://avatars2.githubusercontent.com/u/20454213?s=460&v=4", - "role": "Lead Developer", - "twitter": "FredWessberg" - } - ], - "license": "MIT", - "devDependencies": { - "@wessberg/scaffold": "1.0.19", - "@wessberg/rollup-plugin-ts": "1.1.66", - "@wessberg/ts-config": "0.0.41", - "standard-changelog": "2.0.15", - "tslint": "5.20.0", - "ava": "2.4.0", - "prettier": "^1.18.2", - "pretty-quick": "^2.0.0", - "husky": "^3.0.9", - "np": "^5.1.1", - "find-up": "^4.1.0", - "ts-node": "^8.4.1", - "rollup": "^1.23.1" - }, - "dependencies": { - "@types/deasync": "0.1.0", - "@types/node": "12.7.12", - "@types/object-path": "0.11.0", - "chalk": "2.4.2", - "object-path": "0.11.4", - "tslib": "1.10.0", - "typescript": "3.6.4" - }, - "optionalDependencies": { - "@types/jsdom": "12.2.4", - "jsdom": "15.1.1", - "deasync": "0.1.15" - }, - "main": "./dist/cjs/index.js", - "module": "./dist/esm/index.js", - "browser": "./dist/esm/index.js", - "types": "./dist/esm/index.d.ts", - "typings": "./dist/esm/index.d.ts", - "es2015": "./dist/esm/index.js", - "repository": { - "type": "git", - "url": "https://github.com/wessberg/ts-evaluator.git" - }, - "bugs": { - "url": "https://github.com/wessberg/ts-evaluator/issues" - }, - "engines": { - "node": ">=10.1.0" - }, - "ava": { - "files": [ - "test/**/*.test.ts" - ], - "compileEnhancements": false, - "extensions": [ - "ts" - ], - "require": [ - "ts-node/register" - ] - } + "name": "@wessberg/ts-evaluator", + "version": "0.0.23", + "description": "An interpreter for Typescript that can evaluate an arbitrary Node within a Typescript AST", + "scripts": { + "generate:readme": "scaffold readme --yes", + "generate:license": "scaffold license --yes", + "generate:contributing": "scaffold contributing --yes", + "generate:coc": "scaffold coc --yes", + "generate:changelog": "standard-changelog --first-release", + "generate:all": "npm run generate:license & npm run generate:contributing & npm run generate:coc & npm run generate:readme && npm run generate:changelog", + "clean": "rm -rf dist", + "lint": "tsc --noEmit && tslint -c tslint.json --project tsconfig.json", + "prettier": "prettier --write '{src,test,documentation}/**/*.{js,ts,json,html,xml,css,md}'", + "test": "ava", + "prebuild": "npm run clean", + "build": "npm run rollup", + "rollup": "rollup -c rollup.config.js", + "preversion": "npm run lint && NODE_ENV=production npm run build", + "version": "npm run generate:all && git add .", + "release": "np --no-cleanup --no-yarn" + }, + "keywords": [ + "typescript", + "ts", + "interpreter", + "evaluate", + "evaluator", + "ast" + ], + "files": [ + "dist/**/*.*" + ], + "contributors": [ + { + "name": "Frederik Wessberg", + "email": "frederikwessberg@hotmail.com", + "url": "https://github.com/wessberg", + "imageUrl": "https://avatars2.githubusercontent.com/u/20454213?s=460&v=4", + "role": "Lead Developer", + "twitter": "FredWessberg", + "github": "wessberg" + } + ], + "license": "MIT", + "devDependencies": { + "@wessberg/scaffold": "1.0.19", + "@wessberg/rollup-plugin-ts": "1.1.74", + "@wessberg/ts-config": "0.0.42", + "standard-changelog": "2.0.15", + "tslint": "5.20.1", + "ava": "2.4.0", + "prettier": "^1.19.1", + "pretty-quick": "^2.0.1", + "husky": "^3.0.9", + "np": "^5.1.3", + "find-up": "^4.1.0", + "ts-node": "^8.4.1", + "rollup": "^1.26.4", + "typescript": "3.7.2" + }, + "dependencies": { + "@types/deasync": "0.1.0", + "@types/node": "12.12.7", + "@types/object-path": "0.11.0", + "chalk": "3.0.0", + "object-path": "0.11.4", + "tslib": "1.10.0" + }, + "peerDependencies": { + "typescript": "^3.x" + }, + "optionalDependencies": { + "@types/jsdom": "12.2.4", + "jsdom": "15.2.1", + "deasync": "0.1.15" + }, + "main": "./dist/cjs/index.js", + "module": "./dist/esm/index.js", + "browser": "./dist/esm/index.js", + "types": "./dist/esm/index.d.ts", + "typings": "./dist/esm/index.d.ts", + "es2015": "./dist/esm/index.js", + "repository": { + "type": "git", + "url": "https://github.com/wessberg/ts-evaluator.git" + }, + "bugs": { + "url": "https://github.com/wessberg/ts-evaluator/issues" + }, + "engines": { + "node": ">=10.1.0" + }, + "ava": { + "files": [ + "test/**/*.test.ts" + ], + "compileEnhancements": false, + "extensions": [ + "ts" + ], + "require": [ + "ts-node/register" + ] + } } diff --git a/src/interpreter/evaluator/evaluate-binary-expression.ts b/src/interpreter/evaluator/evaluate-binary-expression.ts index 2c7392c..a00fc4a 100644 --- a/src/interpreter/evaluator/evaluate-binary-expression.ts +++ b/src/interpreter/evaluator/evaluate-binary-expression.ts @@ -180,6 +180,10 @@ export function evaluateBinaryExpression ({node, environment, evaluate, logger, return leftValue in (rightValue as unknown as object); } + // Nullish coalescing (A ?? B) + case SyntaxKind.QuestionQuestionToken: + return leftValue != null ? leftValue : rightValue; + case SyntaxKind.InstanceOfKeyword: { return leftValue as unknown as object instanceof (rightValue as unknown as Function); } diff --git a/src/interpreter/evaluator/evaluate-call-expression.ts b/src/interpreter/evaluator/evaluate-call-expression.ts index be3443a..8cf6fe6 100644 --- a/src/interpreter/evaluator/evaluate-call-expression.ts +++ b/src/interpreter/evaluator/evaluate-call-expression.ts @@ -20,7 +20,7 @@ export function evaluateCallExpression ({node, environment, evaluate, statementT } // Evaluate the expression - const expressionResult = (evaluate.expression(node.expression, environment, statementTraversalStack)) as Function; + const expressionResult = (evaluate.expression(node.expression, environment, statementTraversalStack)) as Function|undefined; if (isLazyCall(expressionResult)) { const currentThisBinding = expressionContainsSuperKeyword(node.expression) ? getFromLexicalEnvironment(node, environment, THIS_SYMBOL) : undefined; @@ -36,11 +36,12 @@ export function evaluateCallExpression ({node, environment, evaluate, statementT // Otherwise, assume that the expression still needs calling else { - if (typeof expressionResult !== "function") { + // Unless optional chaining is being used, throw a NotCallableError + if (node.questionDotToken == null && typeof expressionResult !== "function") { throw new NotCallableError({value: expressionResult, node: node.expression}); } - const value = expressionResult(...evaluatedArgs); + const value = typeof expressionResult !== "function" ? undefined : expressionResult(...evaluatedArgs); logger.logResult(value, "CallExpression"); return value; } diff --git a/src/interpreter/evaluator/evaluate-element-access-expression.ts b/src/interpreter/evaluator/evaluate-element-access-expression.ts index a8c307f..28cb91d 100644 --- a/src/interpreter/evaluator/evaluate-element-access-expression.ts +++ b/src/interpreter/evaluator/evaluate-element-access-expression.ts @@ -12,7 +12,11 @@ export function evaluateElementAccessExpression ({node, environment, evaluate, s const expressionResult = (evaluate.expression(node.expression, environment, statementTraversalStack)) as IndexLiteral; const argumentExpressionResult = (evaluate.expression(node.argumentExpression, environment, statementTraversalStack)) as IndexLiteralKey; - const match = expressionResult[argumentExpressionResult]; + + const match = node.questionDotToken != null && expressionResult == null + // If optional chaining are being used and the expressionResult is undefined or null, assign undefined to 'match' + ? undefined + : expressionResult[argumentExpressionResult]; // If it is a function, wrap it in a lazy call to preserve implicit this bindings. This is to avoid losing the this binding or having to // explicitly bind a 'this' value diff --git a/src/interpreter/evaluator/evaluate-property-access-expression.ts b/src/interpreter/evaluator/evaluate-property-access-expression.ts index ea893e4..72cdd34 100644 --- a/src/interpreter/evaluator/evaluate-property-access-expression.ts +++ b/src/interpreter/evaluator/evaluate-property-access-expression.ts @@ -10,7 +10,11 @@ import {isBindCallApply} from "../util/function/is-bind-call-apply"; */ export function evaluatePropertyAccessExpression ({node, environment, evaluate, statementTraversalStack}: IEvaluatorOptions): Literal { const expressionResult = (evaluate.expression(node.expression, environment, statementTraversalStack)) as IndexLiteral; - const match = expressionResult[node.name.text]; + + const match = node.questionDotToken != null && expressionResult == null + // If optional chaining are being used and the expressionResult is undefined or null, assign undefined to 'match' + ? undefined + : expressionResult[node.name.text]; // If it is a function, wrap it in a lazy call to preserve implicit 'this' bindings. This is to avoid losing the 'this' binding or having to // explicitly bind a 'this' value diff --git a/test/nullish-coalescing/nullish-coalescing.test.ts b/test/nullish-coalescing/nullish-coalescing.test.ts new file mode 100644 index 0000000..7336255 --- /dev/null +++ b/test/nullish-coalescing/nullish-coalescing.test.ts @@ -0,0 +1,20 @@ +import test from "ava"; +import {prepareTest} from "../setup"; + +test("Supports nullish coalescing with null-like values. #1", t => { + const {evaluate} = prepareTest( + // language=TypeScript + ` + const foo = ""; + const bar = foo ?? "bar"; + `, + `foo ?? "bar"` + ); + + const result = evaluate(); + + if (!result.success) t.fail(result.reason.stack); + else { + t.deepEqual(result.value, ""); + } +}); \ No newline at end of file diff --git a/test/optional-chaining/optional-chaining.test.ts b/test/optional-chaining/optional-chaining.test.ts new file mode 100644 index 0000000..15eb9c9 --- /dev/null +++ b/test/optional-chaining/optional-chaining.test.ts @@ -0,0 +1,56 @@ +import test from "ava"; +import {prepareTest} from "../setup"; + +test("Supports optional CallExpressions. #1", t => { + const {evaluate} = prepareTest( + // language=TypeScript + ` + const foo = {bar: {baz: undefined}}; + const bar = foo.bar.baz?.(); + `, + "foo.bar.baz?.()" + ); + + const result = evaluate(); + + if (!result.success) t.fail(result.reason.stack); + else { + t.deepEqual(result.value, undefined); + } +}); + +test("Supports optional PropertyAccessExpressions. #1", t => { + const {evaluate} = prepareTest( + // language=TypeScript + ` + const foo = {bar: undefined}; + const bar = foo.bar?.baz; + `, + "foo.bar?.baz" + ); + + const result = evaluate(); + + if (!result.success) t.fail(result.reason.stack); + else { + t.deepEqual(result.value, undefined); + } +}); + +test("Supports optional ElementAccessExpressions. #1", t => { + const {evaluate} = prepareTest( + // language=TypeScript + ` + const foo = {bar: undefined}; + const bar = foo.bar?.["baz"]; + `, + `foo.bar?.["baz"]` + ); + + const result = evaluate(); + + if (!result.success) t.fail(result.reason.stack); + else { + t.deepEqual(result.value, undefined); + } +}); \ No newline at end of file