├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .travis.yml ├── README.md ├── package.json ├── src ├── index.js └── stdlib.js ├── test ├── fixtures │ ├── arrow-function-expressions │ │ ├── async │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── basic │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── curly │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-async │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-basic │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-generator-void │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-oneline │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-twoline-unfortunate │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-void │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── generator-curly │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── generator-void │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── generator │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── one-param-no-paren-async │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── one-param-no-paren-fat │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── one-param-no-paren │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── one-param-paren │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── oneline │ │ │ ├── actual.js │ │ │ └── expected.js │ │ └── void │ │ │ ├── actual.js │ │ │ └── expected.js │ ├── arrow-methods-class │ │ ├── computed-fat-generator │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── computed-skinny │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-async │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-basic │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-extends-branched-super │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-extends-no-constructor │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-extends-no-super │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-extends-super │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-generator │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-nested-class-super │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-static-declaration-computed │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-static-declaration │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-static-expression-assign-member │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-static-expression-assign │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-static-expression-var │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-static-expression │ │ │ ├── actual.js │ │ │ ├── exec.js │ │ │ └── expected.js │ │ ├── fat-with-constructor │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-basic │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-curly │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-extends-no-constructor │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-extends-no-super-args │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-extends-no-super │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-get │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-oneline │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-set │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-static │ │ │ ├── actual.js │ │ │ └── expected.js │ │ └── skinny-void │ │ │ ├── actual.js │ │ │ └── expected.js │ ├── arrow-methods-obj │ │ ├── computed-fat-generator │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── computed-skinny │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-assign │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-async │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-basic │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-generator │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-member │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-no-assign │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-async │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-basic │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-curly │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-generator │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-get │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-oneline │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── skinny-set │ │ │ ├── actual.js │ │ │ └── expected.js │ │ └── skinny-void │ │ │ ├── actual.js │ │ │ └── expected.js │ ├── await-arrow │ │ ├── assign-member │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── assign-pattern │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── assign │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── await-array │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── safe-assign │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── safe-statement │ │ │ ├── actual.js │ │ │ └── expected.js │ │ └── statement │ │ │ ├── actual.js │ │ │ └── expected.js │ ├── comprehensions │ │ ├── assignment-expr │ │ │ ├── actual.js │ │ │ ├── exec.js │ │ │ └── expected.js │ │ ├── await │ │ │ ├── actual.js │ │ │ └── options.json │ │ ├── closure-nested-deep │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── closure-nested-semantic.js │ │ ├── closure-nested │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── closure-semantic.js │ │ ├── closure │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── declared-inner-function-semantic.js │ │ ├── declared-inner-function │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── from.js │ │ ├── if-elif.js │ │ ├── if-else-if.js │ │ ├── if-else.js │ │ ├── if.js │ │ ├── in.js │ │ ├── multiple-for.js │ │ ├── nested.js │ │ ├── object-basic │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── object-declared-inner-function │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── object-if.js │ │ ├── object-malformed-expr-1 │ │ │ ├── actual.js │ │ │ └── options.json │ │ ├── object-malformed-expr-2 │ │ │ ├── actual.js │ │ │ └── options.json │ │ ├── object-nested.js │ │ ├── object-no-parens │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── object.js │ │ ├── of.js │ │ ├── return-inside-fn │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── return │ │ │ ├── actual.js │ │ │ └── options.json │ │ ├── semi.js │ │ ├── variable-decl │ │ │ ├── actual.js │ │ │ └── expected.js │ │ └── yield │ │ │ ├── actual.js │ │ │ └── options.json │ ├── examples │ │ ├── fizzbuzz.js │ │ └── jsx │ │ │ ├── actual.js │ │ │ └── expected.js │ ├── for-in │ │ ├── array-elem-idx.js │ │ ├── array-elem.js │ │ ├── array-identifier │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── array-idx-elem.js │ │ ├── array-idx.js │ │ ├── array-scope-ordering │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── array-scope-register-declaration │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── assign-enhanced-in-without-now │ │ │ ├── actual.js │ │ │ └── options.json │ │ ├── assign-enhanced-in │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── assign-in-without-now │ │ │ ├── actual.js │ │ │ └── options.json │ │ ├── assign-in │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── elem-var-shadowing │ │ │ ├── actual.js │ │ │ └── options.json │ │ ├── evaluate-expr-once │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── if │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── nested-semantic.js │ │ ├── nested │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── not-prefixed │ │ │ ├── actual.js │ │ │ └── options.json │ │ ├── obj-key-val.js │ │ ├── obj-key.js │ │ ├── obj-val-key.js │ │ ├── obj-val.js │ │ ├── object-identifier │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── object-own-properties.js │ │ ├── plain-array │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── plain-object │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── scope-ordering │ │ │ ├── actual.js │ │ │ └── expected.js │ │ └── scope-register-declaration │ │ │ ├── actual.js │ │ │ └── expected.js │ ├── for-of │ │ ├── not-prefixed │ │ │ ├── actual.js │ │ │ └── options.json │ │ └── now │ │ │ ├── actual.js │ │ │ └── expected.js │ ├── for │ │ ├── i-arr-plain.js │ │ ├── i-x-arr-plain.js │ │ ├── in-obj.js │ │ ├── nested.js │ │ ├── of-arr.js │ │ ├── of-obj.js │ │ ├── of-plain.js │ │ ├── semi-semi-colon.js │ │ ├── semi-semi-paren-free.js │ │ └── semi-semi-paren.js │ ├── if-expressions │ │ ├── blocks │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── no-alternate │ │ │ ├── actual.js │ │ │ └── expected.js │ │ └── oneline │ │ │ ├── actual.js │ │ │ └── expected.js │ ├── implicit-returns │ │ ├── assign │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── await-assign │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── basic.js │ │ ├── branched.js │ │ ├── const │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── constructor-no-return │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── curly.js │ │ ├── inner-functions-arrow │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── inner-functions │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── loop-branched-one-retval │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── loop.js │ │ ├── member-assign │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── set-no-return │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── void-assign │ │ │ ├── actual.js │ │ │ └── expected.js │ │ └── void │ │ │ ├── actual.js │ │ │ └── expected.js │ ├── named-arrow-functions │ │ ├── async │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── basic │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── curly │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-async │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-basic │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-generator-expression │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-generator-statement │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-oneline │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── fat-twoline-unfortunate │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── function-expressions-fat-unfortunate │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── function-expressions │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── generator-curly │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── generator-void │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── generator │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── member-fat-generator │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── member-fat │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── member │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── oneline │ │ │ ├── actual.js │ │ │ └── expected.js │ │ └── void │ │ │ ├── actual.js │ │ │ └── expected.js │ ├── options.json │ ├── safe-member-expression │ │ ├── basic │ │ │ ├── actual.js │ │ │ ├── exec.js │ │ │ └── expected.js │ │ ├── calls-after │ │ │ ├── actual.js │ │ │ ├── exec.js │ │ │ └── expected.js │ │ ├── chained │ │ │ ├── actual.js │ │ │ ├── exec.js │ │ │ └── expected.js │ │ └── computed │ │ │ ├── actual.js │ │ │ ├── exec.js │ │ │ └── expected.js │ ├── stdlib │ │ ├── bitwise-ops │ │ │ ├── actual.js │ │ │ ├── exec.js │ │ │ └── expected.js │ │ ├── disabled │ │ │ ├── actual.js │ │ │ ├── expected.js │ │ │ └── options.json │ │ ├── kitchen-sink │ │ │ ├── actual.js │ │ │ └── expected.js │ │ ├── lightscript-disabled │ │ │ ├── actual.js │ │ │ ├── expected.js │ │ │ └── options.json │ │ ├── lightscript-stdlib-works │ │ │ ├── exec.js │ │ │ └── options.json │ │ ├── lodash-disabled │ │ │ ├── actual.js │ │ │ ├── expected.js │ │ │ └── options.json │ │ ├── lodash-true │ │ │ ├── actual.js │ │ │ ├── expected.js │ │ │ └── options.json │ │ ├── overridden │ │ │ ├── actual.js │ │ │ └── expected.js │ │ └── require-true │ │ │ ├── actual.js │ │ │ ├── exec.js │ │ │ ├── expected.js │ │ │ └── options.json │ ├── tilde-calls │ │ ├── basic.js │ │ └── subscripts.js │ └── variables │ │ ├── for-in-elem │ │ ├── actual.js │ │ └── options.json │ │ ├── for-in-idx │ │ ├── actual.js │ │ └── options.json │ │ ├── for-in-key │ │ ├── actual.js │ │ └── options.json │ │ ├── for-in-val │ │ ├── actual.js │ │ └── options.json │ │ ├── function │ │ ├── actual.js │ │ └── options.json │ │ ├── no-now-update-assignment │ │ ├── actual.js │ │ └── options.json │ │ ├── now-member │ │ ├── actual.js │ │ └── expected.js │ │ ├── now-missing │ │ ├── actual.js │ │ └── options.json │ │ ├── now-update-assignment │ │ ├── actual.js │ │ └── expected.js │ │ ├── now-update-expression │ │ ├── actual.js │ │ └── expected.js │ │ ├── shadow-basic │ │ ├── actual.js │ │ └── options.json │ │ ├── shadow-destructured │ │ ├── actual.js │ │ └── options.json │ │ ├── shadow-explicit │ │ ├── actual.js │ │ └── expected.js │ │ ├── shadow-method-sibling │ │ ├── actual.js │ │ └── expected.js │ │ ├── shadow-nested │ │ ├── actual.js │ │ └── options.json │ │ ├── shadow-same-level-dup │ │ ├── actual.js │ │ └── options.json │ │ ├── shadow-sibling-function │ │ ├── actual.js │ │ └── expected.js │ │ ├── shadow-sibling │ │ ├── actual.js │ │ └── expected.js │ │ └── shadow-toplevel-dup │ │ ├── actual.js │ │ └── options.json └── index.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["env", { "targets": { "node": 4 } }]], 3 | "plugins": ["add-module-exports", "transform-flow-strip-types"] 4 | } 5 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["babel"], 3 | "rules": { 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | /index.js 4 | /stdlib.js 5 | npm-debug.log 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '6' 4 | - '7' 5 | 6 | before_script: 7 | - npm run build 8 | - npm link 9 | - npm link babel-plugin-lightscript 10 | - npm run build 11 | 12 | notifications: 13 | email: false 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # babel-plugin-lightscript 2 | 3 | Compiles [LightScript](http://lightscript.org) to JavasScript when used with [Babel](http://babeljs.io). 4 | 5 | The plugin only processes files that include `.lsc` or `.lsx` in their filenames. 6 | 7 | It converts a "LightScript AST" produced by [babylon-lightscript](https://github.com/lightscript/babylon-lightscript) 8 | into a conventional "Babel AST". 9 | 10 | If you are using ES7 features (like `import`), JSX, and Flow, use 11 | [babel-preset-lightscript](https://github.com/lightscript/babel-preset-lightscript) 12 | to target ES6 instead of using the plugin directly. 13 | 14 | If you are using `babel-plugin-lightscript` with other plugins, be sure it is the *first* plugin. 15 | 16 | ### Options 17 | 18 | You may disable the standard library: 19 | 20 | { 21 | "plugins": [ 22 | ["lightscript", { "stdlib": false }] 23 | ] 24 | } 25 | 26 | Or disable its inclusion of lodash: 27 | 28 | { 29 | "plugins": [ 30 | ["lightscript", { 31 | "stdlib": { 32 | "lodash": false, 33 | } 34 | }] 35 | ] 36 | } 37 | 38 | Or tell it to use `require()` instead of `import`: 39 | 40 | { 41 | "plugins": [ 42 | ["lightscript", { 43 | "stdlib": { 44 | "require": true, 45 | } 46 | }] 47 | ] 48 | } 49 | 50 | 51 | ### Contributing 52 | 53 | You will need to link `babel-plugin-lightscript` to itself: 54 | 55 | cd babel-plugin-lightscript 56 | npm link 57 | npm link babel-plugin-lightscript 58 | npm install 59 | npm run build 60 | npm test 61 | 62 | Please report issues on [the main lightscript repo](https://github.com/lightscript/lightscript) instead of here. 63 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babel-plugin-lightscript", 3 | "version": "0.5.9", 4 | "description": "Compile LightScript to JavaScript.", 5 | "main": "index.js", 6 | "engines": { 7 | "node": ">=4" 8 | }, 9 | "scripts": { 10 | "test": "mocha test", 11 | "test:debug": "node --inspect --debug-brk mocha test", 12 | "build": "babel src --out-dir .", 13 | "start": "babel src --out-dir . --watch", 14 | "preversion": "npm run build && npm test" 15 | }, 16 | "author": "Alex Rattray (http://alexrattray.com/)", 17 | "homepage": "http://lightscript.org/", 18 | "license": "MIT", 19 | "dependencies": { 20 | "babylon-lightscript": "0.5.9" 21 | }, 22 | "files": [ 23 | "stdlib.js", 24 | "index.js" 25 | ], 26 | "devDependencies": { 27 | "babel-cli": "^6.22.2", 28 | "babel-core": "^6.18.2", 29 | "babel-eslint": "^7.0.0", 30 | "babel-helper-plugin-test-runner": "^6.18.0", 31 | "babel-plugin-add-module-exports": "^0.2.1", 32 | "babel-plugin-syntax-jsx": "^6.18.0", 33 | "babel-plugin-transform-flow-strip-types": "^6.22.0", 34 | "babel-preset-env": "^1.3.2", 35 | "eslint": "^3.10.2", 36 | "eslint-config-babel": "^3.0.0", 37 | "eslint-plugin-babel": "^4.0.0", 38 | "eslint-plugin-flowtype": "^2.4.0", 39 | "mocha": "^3.2.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { parse } from "babylon-lightscript"; 2 | import { defaultImports, lightscriptImports, lodashImports } from "./stdlib"; 3 | 4 | export default function (babel) { 5 | const { types: t } = babel; 6 | 7 | // BABEL-TYPES copypasta; see https://github.com/babel/babel/pull/4886 8 | /* eslint-disable no-unused-vars */ 9 | 10 | function getType(val) { 11 | if (Array.isArray(val)) { 12 | return "array"; 13 | } else if (val === null) { 14 | return "null"; 15 | } else if (val === undefined) { 16 | return "undefined"; 17 | } else { 18 | return typeof val; 19 | } 20 | } 21 | 22 | function assertEach(callback: Function): Function { 23 | function validator(node, key, val) { 24 | if (!Array.isArray(val)) return; 25 | 26 | for (let i = 0; i < val.length; i++) { 27 | callback(node, `${key}[${i}]`, val[i]); 28 | } 29 | } 30 | validator.each = callback; 31 | return validator; 32 | } 33 | 34 | function assertOneOf(...vals): Function { 35 | function validate(node, key, val) { 36 | if (vals.indexOf(val) < 0) { 37 | throw new TypeError( 38 | `Property ${key} expected value to be one of ${JSON.stringify(vals)} but got ${JSON.stringify(val)}` 39 | ); 40 | } 41 | } 42 | 43 | validate.oneOf = vals; 44 | 45 | return validate; 46 | } 47 | 48 | function assertNodeType(...types: Array): Function { 49 | function validate(node, key, val) { 50 | let valid = false; 51 | 52 | for (const type of types) { 53 | if (t.is(type, val)) { 54 | valid = true; 55 | break; 56 | } 57 | } 58 | 59 | if (!valid) { 60 | throw new TypeError( 61 | `Property ${key} of ${node.type} expected node to be of a type ${JSON.stringify(types)} ` + 62 | `but instead got ${JSON.stringify(val && val.type)}` 63 | ); 64 | } 65 | } 66 | 67 | validate.oneOfNodeTypes = types; 68 | 69 | return validate; 70 | } 71 | 72 | function assertNodeOrValueType(...types: Array): Function { 73 | function validate(node, key, val) { 74 | let valid = false; 75 | 76 | for (const type of types) { 77 | if (getType(val) === type || t.is(type, val)) { 78 | valid = true; 79 | break; 80 | } 81 | } 82 | 83 | if (!valid) { 84 | throw new TypeError( 85 | `Property ${key} of ${node.type} expected node to be of a type ${JSON.stringify(types)} ` + 86 | `but instead got ${JSON.stringify(val && val.type)}` 87 | ); 88 | } 89 | } 90 | 91 | validate.oneOfNodeOrValueTypes = types; 92 | 93 | return validate; 94 | } 95 | 96 | function assertValueType(type: string): Function { 97 | function validate(node, key, val) { 98 | const valid = getType(val) === type; 99 | 100 | if (!valid) { 101 | throw new TypeError(`Property ${key} expected type of ${type} but got ${getType(val)}`); 102 | } 103 | } 104 | 105 | validate.type = type; 106 | 107 | return validate; 108 | } 109 | 110 | function chain(...fns: Array): Function { 111 | function validate(...args) { 112 | for (const fn of fns) { 113 | fn(...args); 114 | } 115 | } 116 | validate.chainOf = fns; 117 | return validate; 118 | } 119 | 120 | /* eslint-enable no-unused-vars */ 121 | 122 | function definePluginType( 123 | type: string, 124 | opts: { 125 | fields?: Object; 126 | visitor?: Array; 127 | aliases?: Array; 128 | builder?: Array; 129 | inherits?: string; 130 | deprecatedAlias?: string; 131 | } = {}, 132 | ) { 133 | const inherits = {}; 134 | if (opts.inherits) { 135 | inherits.visitor = t.VISITOR_KEYS[opts.inherits]; 136 | inherits.builder = t.BUILDER_KEYS[opts.inherits]; 137 | inherits.fields = t.NODE_FIELDS[opts.inherits]; 138 | inherits.aliases = t.ALIAS_KEYS[opts.inherits]; 139 | } 140 | 141 | opts.fields = opts.fields || inherits.fields || {}; 142 | opts.visitor = opts.visitor || inherits.visitor || []; 143 | opts.aliases = opts.aliases || inherits.aliases || []; 144 | opts.builder = opts.builder || inherits.builder || opts.visitor || []; 145 | 146 | if (opts.deprecatedAlias) { 147 | t.DEPRECATED_KEYS[opts.deprecatedAlias] = type; 148 | } 149 | 150 | // ensure all field keys are represented in `fields` 151 | for (const key of (opts.visitor.concat(opts.builder): Array)) { 152 | opts.fields[key] = opts.fields[key] || {}; 153 | } 154 | 155 | for (const key in opts.fields) { 156 | const field = opts.fields[key]; 157 | 158 | if (opts.builder.indexOf(key) === -1) { 159 | field.optional = true; 160 | } 161 | if (field.default === undefined) { 162 | field.default = null; 163 | } else if (!field.validate) { 164 | field.validate = assertValueType(getType(field.default)); 165 | } 166 | } 167 | 168 | t.VISITOR_KEYS[type] = opts.visitor; 169 | t.BUILDER_KEYS[type] = opts.builder; 170 | t.NODE_FIELDS[type] = opts.fields; 171 | t.ALIAS_KEYS[type] = opts.aliases; 172 | 173 | // the below should not be necessary; see https://github.com/babel/babel/pull/4886 174 | t.TYPES.push(type); 175 | 176 | opts.aliases.forEach((alias) => { 177 | t.FLIPPED_ALIAS_KEYS[alias] = t.FLIPPED_ALIAS_KEYS[alias] || [alias]; 178 | t.FLIPPED_ALIAS_KEYS[alias].push(type); 179 | 180 | if (!t.TYPES[alias]) t.TYPES.push(alias); 181 | }); 182 | } 183 | 184 | 185 | // HELPER FUNCTIONS 186 | function isFunctionDeclaration(node) { 187 | return node && (t.is("FunctionDeclaration", node) || node.type === "NamedArrowDeclaration"); 188 | } 189 | 190 | function transformTails(path, allowLoops, getNewNode) { 191 | path.resync(); 192 | 193 | const tailPaths = getTailExpressions(path.get("body"), allowLoops); 194 | for (const tailPath of tailPaths) { 195 | if (!tailPath) continue; 196 | 197 | if (tailPath.isExpressionStatement()) { 198 | tailPath.replaceWith(getNewNode(tailPath.node.expression, tailPath)); 199 | } else if (tailPath.isVariableDeclaration()) { 200 | // TODO: handle declarations.length > 1 201 | // TODO: add linting to discourage 202 | tailPath.insertAfter(getNewNode(tailPath.node.declarations[0].id, tailPath)); 203 | } else if (isFunctionDeclaration(tailPath.node)) { 204 | // Need to transform exprs to statements since this is block context. 205 | const nextNode = getNewNode(tailPath.node.id, tailPath); 206 | if (t.isExpression(nextNode)) { 207 | tailPath.insertAfter(t.expressionStatement(nextNode)); 208 | } else { 209 | tailPath.insertAfter(nextNode); 210 | } 211 | } 212 | } 213 | } 214 | 215 | function validateComprehensionLoopBody(loopBodyPath) { 216 | loopBodyPath.traverse({ 217 | Function(fnPath) { 218 | fnPath.skip(); 219 | }, 220 | AwaitExpression(awaitPath) { 221 | throw awaitPath.buildCodeFrameError( 222 | "`await` is not allowed within Comprehensions; " + 223 | "instead, await the Comprehension (eg; `y <- [for x of xs: x]`)." 224 | ); 225 | }, 226 | YieldExpression(yieldPath) { 227 | throw yieldPath.buildCodeFrameError("`yield` is not allowed within Comprehensions."); 228 | }, 229 | ReturnStatement(returnPath) { 230 | throw returnPath.buildCodeFrameError("`return` is not allowed within Comprehensions."); 231 | }, 232 | }); 233 | } 234 | 235 | function wrapComprehensionInIife(bodyVarId, bodyVarInitializer, loopBody) { 236 | const fn = t.arrowFunctionExpression([], t.blockStatement([ 237 | t.variableDeclaration( 238 | "const", 239 | [t.variableDeclarator(bodyVarId, bodyVarInitializer)] 240 | ), 241 | loopBody, 242 | t.returnStatement(bodyVarId), 243 | ])); 244 | 245 | return t.callExpression(fn, []); 246 | } 247 | 248 | function toBlockStatement(body) { 249 | if (!t.isBlockStatement(body)) { 250 | if (!t.isStatement(body)) { 251 | body = t.expressionStatement(body); 252 | } 253 | body = t.blockStatement([body]); 254 | } 255 | return body; 256 | } 257 | 258 | function ensureBlockBody(path) { 259 | if (!t.isBlockStatement(path.node.body)) { 260 | path.get("body").replaceWith(t.blockStatement([path.node.body])); 261 | } 262 | } 263 | 264 | function toPlainFunction(node) { 265 | let { id, params, body, generator, async } = node; 266 | 267 | body = toBlockStatement(body); 268 | 269 | const fn = t.isStatement(node) 270 | ? t.functionDeclaration(id, params, body, generator, async) 271 | : t.functionExpression(id, params, body, generator, async); 272 | 273 | if (node.returnType) fn.returnType = node.returnType; 274 | if (node.typeParameters) fn.typeParameters = node.typeParameters; 275 | return fn; 276 | } 277 | 278 | function replaceWithPlainFunction(path) { 279 | path.replaceWith(toPlainFunction(path.node)); 280 | } 281 | 282 | function toArrowFunction(node) { 283 | let { id, params, body, async } = node; 284 | 285 | if (t.isStatement(node)) { 286 | let fn = t.arrowFunctionExpression(params, body, async); 287 | if (node.returnType) fn.returnType = node.returnType; 288 | if (node.typeParameters) fn.typeParameters = node.typeParameters; 289 | return t.variableDeclaration("const", [t.variableDeclarator(id, fn)]); 290 | } else { 291 | // just throw away the id for now... 292 | // TODO: think of a way to use it? or outlaw named fat-arrow expressions? 293 | let fn = t.arrowFunctionExpression(params, body, async); 294 | if (node.returnType) fn.returnType = node.returnType; 295 | if (node.typeParameters) fn.typeParameters = node.typeParameters; 296 | return fn; 297 | } 298 | } 299 | 300 | function replaceWithArrowFunction(path) { 301 | const id = path.get("id"); 302 | path.replaceWith(toArrowFunction(path.node)); 303 | path.scope.registerBinding("const", id); 304 | } 305 | 306 | function replaceWithBoundFunction(path) { 307 | const isStatement = t.isStatement(path.node); 308 | 309 | if (isStatement) { 310 | replaceWithPlainFunction(path); 311 | 312 | const bound = t.callExpression( 313 | t.memberExpression(path.node.id, t.identifier("bind")), 314 | [t.thisExpression()] 315 | ); 316 | const assignToBound = t.expressionStatement(t.assignmentExpression("=", 317 | path.node.id, 318 | bound 319 | )); 320 | 321 | path.insertAfter(assignToBound); 322 | } else { 323 | const unbound = toPlainFunction(path.node); 324 | const bound = t.callExpression( 325 | t.memberExpression(unbound, t.identifier("bind")), 326 | [t.thisExpression()] 327 | ); 328 | path.replaceWith(bound); 329 | } 330 | } 331 | 332 | function isNamedArrowFunction(node) { 333 | return (typeof node.skinny === "boolean"); 334 | } 335 | 336 | // c/p babel-traverse/src/path/family.js getCompletionRecords 337 | function getTailExpressions(path, allowLoops) { 338 | let paths = []; 339 | 340 | const add = function add(_path) { 341 | if (_path) paths = paths.concat(getTailExpressions(_path, allowLoops)); 342 | }; 343 | 344 | if (path.isIfStatement()) { 345 | add(path.get("consequent")); 346 | add(path.get("alternate")); 347 | } else if (path.isDoExpression()) { 348 | add(path.get("body")); 349 | } else if (allowLoops && (path.isFor() || path.isWhile())) { 350 | add(path.get("body")); 351 | } else if (path.isProgram() || path.isBlockStatement()) { 352 | add(path.get("body").pop()); 353 | } else if (path.isTryStatement()) { 354 | add(path.get("block")); 355 | add(path.get("handler")); 356 | add(path.get("finalizer")); 357 | } else { 358 | paths.push(path); 359 | } 360 | 361 | return paths; 362 | } 363 | 364 | // c/p from replaceExpressionWithStatements 365 | 366 | function addImplicitReturns(path) { 367 | transformTails(path, false, (expr) => { 368 | if (t.isAwaitExpression(expr)) { 369 | return t.returnStatement(expr.argument); 370 | } 371 | 372 | return t.returnStatement(expr); 373 | }); 374 | } 375 | 376 | function containsSuperCall(path) { 377 | let hasSuper = false; 378 | path.traverse({ 379 | Class(classPath) { 380 | classPath.skip(); 381 | }, 382 | Super(superPath) { 383 | if (superPath.parentPath.isCallExpression()) { 384 | hasSuper = true; 385 | superPath.stop(); 386 | } 387 | } 388 | }); 389 | return hasSuper; 390 | } 391 | 392 | function ensureConstructorWithSuper(path, constructorPath) { 393 | path.resync(); // uhh, just in case? 394 | let { node } = path; 395 | 396 | // add empty constructor if it wasn't there 397 | if (!constructorPath) { 398 | let emptyConstructor = t.classMethod("constructor", t.identifier("constructor"), 399 | [], t.blockStatement([])); 400 | emptyConstructor.skinny = true; // mark for super insertion 401 | path.get("body").unshiftContainer("body", emptyConstructor); 402 | constructorPath = path.get("body.body.0.body"); 403 | } 404 | 405 | // add super if it wasn't there (unless defined with curly braces) 406 | if (node.superClass && constructorPath.parentPath.node.skinny && !containsSuperCall(constructorPath)) { 407 | let superCall; 408 | if (constructorPath.parentPath.node.params.length) { 409 | const params = constructorPath.parentPath.node.params; 410 | superCall = t.expressionStatement(t.callExpression(t.super(), params)); 411 | } else { 412 | let argsUid = path.scope.generateUidIdentifier("args"); 413 | let params = [t.restElement(argsUid)]; 414 | superCall = t.expressionStatement(t.callExpression(t.super(), [t.spreadElement(argsUid)])); 415 | constructorPath.parentPath.node.params = params; 416 | } 417 | constructorPath.unshiftContainer("body", superCall); 418 | } 419 | 420 | return constructorPath; 421 | } 422 | 423 | function bindMethodsInConstructor(path, constructorPath, methodIds) { 424 | path.resync(); // uhh, just in case? 425 | let { node } = path; 426 | 427 | // `this.method = this.method.bind(this);` 428 | let assignments = methodIds.map((methodId) => { 429 | assertOneOf(methodId, ["Identifier", "Expression"]); 430 | 431 | let isComputed = !t.isIdentifier(methodId); 432 | let thisDotMethod = t.memberExpression(t.thisExpression(), methodId, isComputed); 433 | let bind = t.callExpression( 434 | t.memberExpression(thisDotMethod, t.identifier("bind")), 435 | [t.thisExpression()] 436 | ); 437 | return t.expressionStatement(t.assignmentExpression("=", thisDotMethod, bind)); 438 | }); 439 | 440 | // directly after each instance of super(), insert the thingies there. 441 | if (node.superClass) { 442 | constructorPath.traverse({ 443 | Class(classPath) { 444 | classPath.skip(); 445 | }, 446 | Super(superPath) { 447 | if (!superPath.parentPath.isCallExpression()) return; 448 | let superStatementPath = superPath.getStatementParent(); 449 | 450 | // things get super weird when you return super(); 451 | // TODO: consider trying to handle it 452 | let enclosingReturn = superPath 453 | .findParent((p) => p.isReturnStatement() && p.getFunctionParent() === constructorPath.parentPath); 454 | if (enclosingReturn) throw new Error("Can't use => with `return super()`; try removing `return`."); 455 | 456 | superStatementPath.insertAfter(assignments); 457 | } 458 | }); 459 | } else { 460 | constructorPath.unshiftContainer("body", assignments); 461 | } 462 | } 463 | 464 | function bindMethods(path, methodIds) { 465 | let assignId, inExpression = false; 466 | if (path.isClassDeclaration()) { 467 | assignId = path.node.id; 468 | } else if ( 469 | path.parentPath.isAssignmentExpression() && 470 | path.parentPath.parentPath.isExpressionStatement() 471 | ) { 472 | assignId = path.parentPath.node.left; 473 | } else if (path.parentPath.isVariableDeclarator()) { 474 | assignId = path.parentPath.node.id; 475 | } else { 476 | let id = path.isClass() ? "class" : "obj"; 477 | assignId = path.getStatementParent().scope.generateDeclaredUidIdentifier(id); 478 | inExpression = true; 479 | } 480 | assertOneOf(assignId, ["Identifier", "MemberExpression"]); 481 | 482 | let assignments = methodIds.map((methodId) => { 483 | // could be computed, eg `['blah']() => {}` 484 | assertOneOf(methodId, ["Identifier", "Expression"]); 485 | let isComputed = !t.isIdentifier(methodId); 486 | let objDotMethod = t.memberExpression(assignId, methodId, isComputed); 487 | let bind = t.callExpression( 488 | t.memberExpression(objDotMethod, t.identifier("bind")), 489 | [assignId] 490 | ); 491 | return t.assignmentExpression("=", objDotMethod, bind); 492 | }); 493 | 494 | if (inExpression) { 495 | path.replaceWith(t.sequenceExpression([ 496 | t.assignmentExpression("=", assignId, path.node), 497 | ...assignments, 498 | assignId 499 | ])); 500 | } else { 501 | path.getStatementParent().insertAfter( 502 | assignments.map((a) => t.expressionStatement(a)) 503 | ); 504 | } 505 | } 506 | 507 | function blockToExpression(path, key) { 508 | if (t.isBlockStatement(path.node[key])) { 509 | path.get(key).canSwapBetweenExpressionAndStatement = () => true; 510 | path.get(key).replaceExpressionWithStatements(path.node[key].body); 511 | } 512 | } 513 | 514 | function checkVariableNotShadowed(path) { 515 | // ignore top-level; same-level will throw a different error. 516 | if (!path.scope.parent) return; 517 | 518 | for (const id in path.get("declarations.0").getBindingIdentifiers()) { 519 | if (path.scope.parent.hasBinding(id)) { 520 | throw path.buildCodeFrameError( 521 | `\`${id}\` is shadowed from a higher scope. ` + 522 | `If you want to reassign the variable, use \`now ${id} = ...\`. ` + 523 | "If you want to declare a new shadowed \`const\` variable, " + 524 | `you must use \`const ${id} = ...\` explicitly.` 525 | ); 526 | } 527 | } 528 | } 529 | 530 | function shouldParseAsLightScript(file) { 531 | if (!file || !file.opts || !file.opts.filename) return true; 532 | const { filename } = file.opts; 533 | // HACK: for lightscript-eslint, and possibly others 534 | if (filename === "unknown") return true; 535 | // for babel-node repl 536 | if (filename === "repl") return true; 537 | 538 | // TODO: consider "peeking" at the first line for a shebang or 'use lightscript' directive. 539 | return ( 540 | // HACK: allow parsing .js test files in this repo. 541 | // TODO: modify `babel-helper-plugin-test-runner` or something instead 542 | filename.includes("test/fixtures") || 543 | filename.includes(".lsc") || 544 | filename.includes(".lsx") 545 | ); 546 | } 547 | 548 | // eg; 'react', 'lodash/fp', './actions' 549 | type ImportPath = string; 550 | 551 | // eg; "React", "PropTypes" 552 | type Specifier = string; 553 | 554 | type Imports = { 555 | [key: ImportPath]: Array, 556 | }; 557 | 558 | type Stdlib = false | { 559 | [key: Specifier]: ImportPath, 560 | }; 561 | 562 | function initializeStdlib(opts): Stdlib { 563 | if (opts.stdlib === false) return false; 564 | 565 | if (typeof opts.stdlib === "object") { 566 | return Object.assign({}, 567 | opts.stdlib.lodash === false ? {} : lodashImports, 568 | opts.stdlib.lightscript === false ? {} : lightscriptImports, 569 | ); 570 | } 571 | 572 | return defaultImports; 573 | } 574 | 575 | function collectStdlibImport(stdlib: Stdlib, imports: Imports, specifier: Specifier) { 576 | if (!stdlib) return; 577 | 578 | const importPath = stdlib[specifier]; 579 | 580 | if (!imports[importPath]) { 581 | imports[importPath] = []; 582 | } 583 | 584 | if (imports[importPath].indexOf(specifier) < 0) { 585 | imports[importPath].push(specifier); 586 | } 587 | } 588 | 589 | function makeInlineStdlibFn(inlineFnName) { 590 | const fnId = t.identifier(inlineFnName); 591 | const aParam = t.identifier("a"); 592 | const bParam = t.identifier("b"); 593 | const op = { 594 | "looseEq": "==", 595 | "looseNotEq": "!=", 596 | "bitwiseNot": "~", 597 | "bitwiseAnd": "&", 598 | "bitwiseOr": "|", 599 | "bitwiseXor": "^", 600 | "bitwiseLeftShift": "<<", 601 | "bitwiseRightShift": ">>", 602 | "bitwiseZeroFillRightShift": ">>>", 603 | }[inlineFnName]; 604 | 605 | // bitwiseNot is the only unary fn; rest are binary. 606 | if (inlineFnName === "bitwiseNot") { 607 | return t.functionDeclaration(fnId, [aParam], t.blockStatement([ 608 | t.returnStatement(t.unaryExpression(op, aParam)), 609 | ])); 610 | } 611 | 612 | return t.functionDeclaration(fnId, [aParam, bParam], t.blockStatement([ 613 | t.returnStatement(t.binaryExpression(op, aParam, bParam)), 614 | ])); 615 | } 616 | 617 | function insertStdlibImports(path, imports: Imports, useRequire) { 618 | const declarations = []; 619 | const inlines = []; 620 | for (const importPath in imports) { 621 | if (importPath === "inline") { 622 | inlines.push(...imports[importPath]); 623 | continue; 624 | } 625 | 626 | const specifierNames = imports[importPath]; 627 | 628 | if (useRequire) { 629 | // eg; `const { map, uniq } = require('lodash');` 630 | for (const specifierName of specifierNames) { 631 | const importIdentifier = t.identifier(specifierName); 632 | 633 | const requireCall = t.callExpression(t.identifier("require"), [ 634 | t.stringLiteral(importPath + "/" + specifierName) 635 | ]); 636 | const requireStmt = t.variableDeclaration("const", [ 637 | t.variableDeclarator(importIdentifier, requireCall), 638 | ]); 639 | 640 | declarations.push(requireStmt); 641 | } 642 | } else { 643 | // eg; `import { map, uniq } from 'lodash';` 644 | for (const specifierName of specifierNames) { 645 | const importIdentifier = t.identifier(specifierName); 646 | const importSpecifier = t.importDefaultSpecifier(importIdentifier); 647 | const importDeclaration = t.importDeclaration( 648 | [importSpecifier], 649 | t.stringLiteral(importPath + "/" + specifierName) 650 | ); 651 | declarations.push(importDeclaration); 652 | } 653 | } 654 | } 655 | path.unshiftContainer("body", declarations); 656 | 657 | if (inlines.length) { 658 | const inlineDeclarations = []; 659 | for (const inlineFnName of inlines) { 660 | inlineDeclarations.push(makeInlineStdlibFn(inlineFnName)); 661 | } 662 | // insert inline fns before the first statement which isn't an import statement 663 | for (const p of path.get("body")) { 664 | if (!p.isImportDeclaration()) { 665 | p.insertBefore(inlineDeclarations); 666 | break; 667 | } 668 | } 669 | } 670 | } 671 | 672 | function generateForInIterator (path, type: "array" | "object") { 673 | const idx = path.node.idx || path.scope.generateUidIdentifier("i"); 674 | const len = path.scope.generateUidIdentifier("len"); 675 | 676 | const initDeclarations = [ 677 | t.variableDeclarator(idx, t.numericLiteral(0)) 678 | ]; 679 | 680 | let refId; 681 | if (path.get(type).isIdentifier()) { 682 | refId = path.node[type]; 683 | } else { 684 | // if the target of iteration is a complex expression, 685 | // create a reference so it only evaluates once 686 | const refName = type === "object" ? "obj" : "arr"; 687 | refId = path.scope.generateUidIdentifier(refName); 688 | initDeclarations.unshift( 689 | t.variableDeclarator( 690 | refId, 691 | path.node[type] 692 | ) 693 | ); 694 | } 695 | 696 | let keys; 697 | if (type === "object") { 698 | keys = path.scope.generateUidIdentifier("keys"); 699 | initDeclarations.push( 700 | t.variableDeclarator(keys, 701 | t.callExpression( 702 | t.memberExpression( 703 | t.identifier("Object"), 704 | t.identifier("keys")), 705 | [refId] 706 | ) 707 | ) 708 | ); 709 | } 710 | 711 | initDeclarations.push( 712 | t.variableDeclarator( 713 | len, 714 | t.memberExpression( 715 | type === "object" ? keys : refId, 716 | t.identifier("length") 717 | ) 718 | ) 719 | ); 720 | 721 | const init = t.variableDeclaration("let", initDeclarations); 722 | // _i < _len 723 | const test = t.binaryExpression("<", idx, len); 724 | // _i++ 725 | const update = t.updateExpression("++", idx); 726 | 727 | ensureBlockBody(path); 728 | const innerDeclarations = []; 729 | if (type === "object") { 730 | const key = path.node.key || path.scope.generateUidIdentifier("k"); 731 | innerDeclarations.push( 732 | t.variableDeclaration("const", [ 733 | t.variableDeclarator(key, t.memberExpression(keys, idx, true)) 734 | ]) 735 | ); 736 | 737 | if (path.node.val) { 738 | innerDeclarations.push( 739 | t.variableDeclaration("const", [ 740 | t.variableDeclarator( 741 | path.node.val, 742 | t.memberExpression(refId, key, true) 743 | ) 744 | ]) 745 | ); 746 | } 747 | } else { 748 | if (path.node.elem) { 749 | innerDeclarations.push( 750 | t.variableDeclaration("const", [ 751 | t.variableDeclarator( 752 | path.node.elem, 753 | t.memberExpression(refId, idx, true) 754 | ) 755 | ]) 756 | ); 757 | } 758 | } 759 | 760 | if (innerDeclarations.length > 0) { 761 | path.get("body").unshiftContainer("body", innerDeclarations); 762 | } 763 | 764 | return t.forStatement(init, test, update, path.node.body); 765 | } 766 | 767 | // TYPE DEFINITIONS 768 | definePluginType("ForInArrayStatement", { 769 | visitor: ["idx", "elem", "array", "body"], 770 | aliases: ["Scopable", "Statement", "For", "BlockParent", "Loop", "ForXStatement", "ForIn"], 771 | fields: { 772 | elem: { 773 | validate: assertNodeType("Identifier"), 774 | optional: true, 775 | }, 776 | idx: { 777 | validate: assertNodeType("Identifier"), 778 | optional: true, 779 | }, 780 | array: { 781 | validate: assertNodeType("Expression"), 782 | }, 783 | body: { 784 | validate: assertNodeType("Statement"), 785 | }, 786 | }, 787 | }); 788 | 789 | definePluginType("ForInObjectStatement", { 790 | visitor: ["key", "val", "object", "body"], 791 | aliases: ["Scopable", "Statement", "For", "BlockParent", "Loop", "ForXStatement", "ForIn"], 792 | fields: { 793 | key: { 794 | validate: assertNodeType("Identifier"), 795 | optional: true, 796 | }, 797 | val: { 798 | validate: assertNodeType("Identifier"), 799 | optional: true, 800 | }, 801 | object: { 802 | validate: assertNodeType("Expression"), 803 | }, 804 | body: { 805 | validate: assertNodeType("Statement"), 806 | }, 807 | }, 808 | }); 809 | 810 | definePluginType("ArrayComprehension", { 811 | visitor: ["loop"], 812 | aliases: ["ArrayExpression", "Expression"], 813 | fields: { 814 | loop: { 815 | validate: assertNodeType("ForStatement"), 816 | }, 817 | }, 818 | }); 819 | 820 | definePluginType("ObjectComprehension", { 821 | visitor: ["loop"], 822 | aliases: ["ObjectExpression", "Expression"], 823 | fields: { 824 | loop: { 825 | validate: assertNodeType("ForStatement"), 826 | }, 827 | }, 828 | }); 829 | 830 | definePluginType("TildeCallExpression", { 831 | visitor: ["left", "right", "arguments"], 832 | aliases: ["CallExpression", "Expression"], 833 | fields: { 834 | left: { 835 | validate: assertNodeType("Expression"), 836 | }, 837 | right: { 838 | validate: assertOneOf("Identifier", "MemberExpression"), 839 | }, 840 | arguments: { 841 | validate: chain( 842 | assertValueType("array"), 843 | assertEach(assertNodeType("Expression", "SpreadElement")) 844 | ), 845 | }, 846 | }, 847 | }); 848 | 849 | definePluginType("NamedArrowDeclaration", { 850 | builder: ["id", "params", "body", "skinny", "async", "generator"], 851 | visitor: ["id", "params", "body", "returnType", "typeParameters"], 852 | aliases: [ 853 | "Scopable", 854 | "Function", 855 | "BlockParent", 856 | "FunctionParent", 857 | "Statement", 858 | "Pureish", 859 | "Declaration", 860 | "FunctionDeclaration", 861 | "NamedArrowFunction", 862 | ], 863 | fields: { // DUP in NamedArrowMemberExpression 864 | id: { 865 | validate: assertNodeType("Identifier"), 866 | }, 867 | params: { 868 | validate: chain( 869 | assertValueType("array"), 870 | assertEach(assertNodeType("LVal")) 871 | ), 872 | }, 873 | body: { 874 | validate: assertNodeType("BlockStatement", "Expression"), 875 | }, 876 | skinny: { 877 | validate: assertValueType("boolean") 878 | }, 879 | generator: { 880 | default: false, 881 | validate: assertValueType("boolean") 882 | }, 883 | async: { 884 | default: false, 885 | validate: assertValueType("boolean") 886 | }, 887 | }, 888 | }); 889 | 890 | definePluginType("NamedArrowExpression", { 891 | inherits: "NamedArrowDeclaration", 892 | aliases: [ 893 | "Scopable", 894 | "Function", 895 | "FunctionExpression", 896 | "BlockParent", 897 | "FunctionParent", 898 | "Expression", 899 | "Pureish", 900 | "NamedArrowFunction", 901 | ], 902 | }); 903 | 904 | definePluginType("NamedArrowMemberExpression", { 905 | inherits: "NamedArrowExpression", 906 | fields: { // c/p from NamedArrowExpression except for `object` 907 | id: { 908 | validate: assertNodeType("Identifier"), 909 | }, 910 | object: { 911 | validate: assertNodeType("Identifier", "MemberExpression"), 912 | }, 913 | params: { 914 | validate: chain( 915 | assertValueType("array"), 916 | assertEach(assertNodeType("LVal")) 917 | ), 918 | }, 919 | body: { 920 | validate: assertNodeType("BlockStatement", "Expression"), 921 | }, 922 | skinny: { 923 | validate: assertValueType("boolean") 924 | }, 925 | generator: { 926 | default: false, 927 | validate: assertValueType("boolean") 928 | }, 929 | async: { 930 | default: false, 931 | validate: assertValueType("boolean") 932 | }, 933 | }, 934 | }); 935 | 936 | definePluginType("IfExpression", { 937 | visitor: ["test", "consequent", "alternate"], 938 | aliases: ["Expression", "Conditional"], 939 | fields: { 940 | test: { 941 | validate: assertNodeType("Expression") 942 | }, 943 | consequent: { 944 | validate: assertNodeType("Expression", "BlockStatement") 945 | }, 946 | alternate: { 947 | optional: true, 948 | validate: assertNodeType("Expression", "BlockStatement") 949 | } 950 | } 951 | }); 952 | 953 | definePluginType("SafeAwaitExpression", { 954 | builder: ["argument"], 955 | visitor: ["argument"], 956 | aliases: ["AwaitExpression", "Expression", "Terminatorless"], 957 | fields: { 958 | argument: { 959 | validate: assertNodeType("Expression"), 960 | } 961 | } 962 | }); 963 | 964 | definePluginType("SafeMemberExpression", { 965 | inherits: "MemberExpression", 966 | aliases: ["MemberExpression", "Expression", "LVal"], 967 | }); 968 | 969 | // traverse as top-level item so as to run before other babel plugins 970 | // (and avoid traversing any of their output) 971 | function Program(path, state) { 972 | if (!shouldParseAsLightScript(state.file)) return; 973 | 974 | const stdlib: Stdlib = initializeStdlib(state.opts); 975 | const useRequire = state.opts.stdlib && state.opts.stdlib.require === true; 976 | const imports: Imports = {}; 977 | 978 | path.traverse({ 979 | 980 | ForInArrayStatement(path) { 981 | path.replaceWith(generateForInIterator(path, "array")); 982 | }, 983 | 984 | ForInObjectStatement(path) { 985 | path.replaceWith(generateForInIterator(path, "object")); 986 | }, 987 | 988 | ArrayComprehension(path) { 989 | validateComprehensionLoopBody(path.get("loop.body")); 990 | 991 | const id = path.scope.generateUidIdentifier("arr"); 992 | transformTails(path.get("loop"), true, (expr) => 993 | t.callExpression( 994 | t.memberExpression(id, t.identifier("push")), 995 | [expr] 996 | ) 997 | ); 998 | 999 | path.replaceWith(wrapComprehensionInIife(id, t.arrayExpression(), path.node.loop)); 1000 | }, 1001 | 1002 | ObjectComprehension(path) { 1003 | validateComprehensionLoopBody(path.get("loop.body")); 1004 | 1005 | const id = path.scope.generateUidIdentifier("obj"); 1006 | transformTails(path.get("loop"), true, function(seqExpr, tailPath) { 1007 | // Only SeqExprs of length 2 are valid. 1008 | if ( 1009 | (seqExpr.type !== "SequenceExpression") || 1010 | (seqExpr.expressions.length !== 2) 1011 | ) { 1012 | throw tailPath.buildCodeFrameError("Object comprehensions must end" + 1013 | " with a (key, value) pair."); 1014 | } 1015 | 1016 | const keyExpr = seqExpr.expressions[0]; 1017 | const valExpr = seqExpr.expressions[1]; 1018 | 1019 | return t.assignmentExpression( 1020 | "=", 1021 | t.memberExpression(id, keyExpr, true), 1022 | valExpr 1023 | ); 1024 | }); 1025 | 1026 | path.replaceWith(wrapComprehensionInIife(id, t.objectExpression([]), path.node.loop)); 1027 | }, 1028 | 1029 | TildeCallExpression: { 1030 | // run on exit instead of enter so that SafeMemberExpression 1031 | // can process differently from a wrapping CallExpression 1032 | // eg; `a?.b~c()` -> `a == null ? null : c(a.b)` 1033 | exit(path) { 1034 | const callExpr = t.callExpression(path.node.right, [ 1035 | path.node.left, 1036 | ...path.node.arguments, 1037 | ]); 1038 | path.replaceWith(callExpr); 1039 | }, 1040 | }, 1041 | 1042 | NamedArrowFunction(path) { 1043 | if (path.node.skinny) { 1044 | replaceWithPlainFunction(path); 1045 | } else if (path.node.generator) { 1046 | // there are no arrow-generators in ES6, so can't compile to arrow 1047 | replaceWithBoundFunction(path); 1048 | } else { 1049 | replaceWithArrowFunction(path); 1050 | } 1051 | }, 1052 | 1053 | NamedArrowMemberExpression(path) { 1054 | let object = path.node.object; 1055 | let node = path.node; 1056 | delete node.object; 1057 | node.type = "NamedArrowExpression"; 1058 | 1059 | if (!node.skinny) { 1060 | node.skinny = true; // binding here, don't turn into arrow 1061 | node = t.callExpression( 1062 | t.memberExpression(node, t.identifier("bind")), 1063 | [object] 1064 | ); 1065 | } 1066 | 1067 | path.replaceWith(t.assignmentExpression("=", 1068 | t.memberExpression(object, path.node.id), 1069 | node, 1070 | )); 1071 | }, 1072 | 1073 | ArrowFunctionExpression(path) { 1074 | if (path.node.skinny) { 1075 | replaceWithPlainFunction(path); 1076 | } else if (path.node.generator) { 1077 | replaceWithBoundFunction(path); 1078 | } 1079 | }, 1080 | 1081 | Method(path) { 1082 | if (isNamedArrowFunction(path.node)) { 1083 | path.node.body = toBlockStatement(path.node.body); 1084 | } 1085 | }, 1086 | 1087 | ClassBody(path) { 1088 | let fatArrows = [], fatStaticArrows = [], constructorPath; 1089 | path.node.body.forEach((method, i) => { 1090 | if (!t.isMethod(method)) return; 1091 | 1092 | if (method.kind === "constructor") { 1093 | constructorPath = path.get(`body.${i}.body`); 1094 | } else if (method.static && method.skinny === false) { 1095 | fatStaticArrows.push(method.key); 1096 | method.skinny = true; // prevent infinite recursion 1097 | } else if (method.skinny === false) { 1098 | fatArrows.push(method.key); 1099 | method.skinny = true; // prevent infinite recursion 1100 | } 1101 | }); 1102 | 1103 | let maybeAddSuper = path.parentPath.node.superClass && constructorPath; 1104 | if (fatArrows.length || maybeAddSuper) { 1105 | constructorPath = ensureConstructorWithSuper(path.parentPath, constructorPath); 1106 | } 1107 | 1108 | if (fatArrows.length) { 1109 | bindMethodsInConstructor(path.parentPath, constructorPath, fatArrows); 1110 | } 1111 | 1112 | if (fatStaticArrows.length) { 1113 | bindMethods(path.parentPath, fatStaticArrows); 1114 | } 1115 | }, 1116 | 1117 | ObjectExpression(path) { 1118 | let fatArrows = []; 1119 | path.node.properties.forEach((prop) => { 1120 | if (t.isMethod(prop) && prop.skinny === false) { 1121 | fatArrows.push(prop.key); 1122 | // bit ugly, but need a way to ensure we don't double-recurse... 1123 | prop.skinny = true; 1124 | } 1125 | }); 1126 | 1127 | if (fatArrows.length) { 1128 | bindMethods(path, fatArrows); 1129 | } 1130 | }, 1131 | 1132 | Function: { 1133 | exit(path) { 1134 | if (path.node.kind === "constructor" || path.node.kind === "set") return; 1135 | 1136 | const isVoid = path.node.returnType && 1137 | t.isVoidTypeAnnotation(path.node.returnType.typeAnnotation); 1138 | 1139 | if (!isVoid) { 1140 | addImplicitReturns(path); 1141 | } 1142 | 1143 | // As this is an exit visitor, other LSC transforms have reduced 1144 | // arrows to plain FunctionDeclarations by this point. 1145 | if (path.node.type === "FunctionDeclaration") { 1146 | // somehow this wasn't being done... may signal deeper issues... 1147 | path.getFunctionParent().scope.registerDeclaration(path); 1148 | } 1149 | } 1150 | }, 1151 | 1152 | IfExpression(path) { 1153 | blockToExpression(path, "consequent"); 1154 | 1155 | if (path.node.alternate) { 1156 | blockToExpression(path, "alternate"); 1157 | } else { 1158 | path.get("alternate").replaceWith(t.nullLiteral()); 1159 | } 1160 | 1161 | path.replaceWith(t.conditionalExpression(path.node.test, path.node.consequent, path.node.alternate)); 1162 | }, 1163 | 1164 | AssignmentExpression(path) { 1165 | if (path.node.operator === "<-" || path.node.operator === " x == null ? x : x.y 1199 | // x?[y] -> x == null ? x : x[y] 1200 | const { node } = path; 1201 | const { object } = node; 1202 | 1203 | let left; 1204 | if (object.type === "Identifier" || object.type === "SafeMemberExpression") { 1205 | left = object; 1206 | } else { 1207 | const ref = path.scope.generateDeclaredUidIdentifier("ref"); 1208 | node.object = ref; 1209 | left = t.assignmentExpression("=", ref, object); 1210 | } 1211 | 1212 | const nullCheck = t.binaryExpression("==", left, t.nullLiteral()); 1213 | node.type = "MemberExpression"; 1214 | path.replaceWith(node); 1215 | 1216 | // Gather trailing subscripts/calls, which are parent nodes: 1217 | // eg; in `o?.x.y()`, group trailing `.x.y()` into the ternary 1218 | let tail = path; 1219 | while (tail.parentPath) { 1220 | const parent = tail.parentPath; 1221 | const hasChainedParent = ( 1222 | parent.isMemberExpression() || 1223 | (parent.isCallExpression() && parent.get("callee") === tail) || 1224 | (parent.node.type === "TildeCallExpression" && parent.get("left") === tail) 1225 | ); 1226 | 1227 | if (hasChainedParent) { 1228 | tail = tail.parentPath; 1229 | } else { 1230 | break; 1231 | } 1232 | } 1233 | 1234 | const ternary = t.conditionalExpression(nullCheck, t.nullLiteral(), tail.node); 1235 | tail.replaceWith(ternary); 1236 | }, 1237 | 1238 | AwaitExpression(path) { 1239 | if (path.get("argument").isArrayExpression() || path.node.argument.type === "ArrayComprehension") { 1240 | const promiseDotAllCall = t.callExpression( 1241 | t.memberExpression(t.identifier("Promise"), t.identifier("all")), 1242 | [path.node.argument], 1243 | ); 1244 | path.get("argument").replaceWith(promiseDotAllCall); 1245 | } 1246 | }, 1247 | 1248 | VariableDeclaration(path) { 1249 | // Error on auto-const when shadowing variable 1250 | if (path.node.kind === "const") { 1251 | if (path.node.extra && path.node.extra.implicit === true) { 1252 | checkVariableNotShadowed(path); 1253 | } 1254 | } 1255 | }, 1256 | 1257 | // collect functions to be imported for the stdlib 1258 | ReferencedIdentifier(path) { 1259 | if (stdlib === false) return; 1260 | 1261 | const { node, scope } = path; 1262 | if (stdlib[node.name] && !scope.hasBinding(node.name)) { 1263 | collectStdlibImport(stdlib, imports, node.name); 1264 | } 1265 | }, 1266 | 1267 | 1268 | }); 1269 | 1270 | insertStdlibImports(path, imports, useRequire); 1271 | } 1272 | 1273 | return { 1274 | manipulateOptions(opts, parserOpts, file) { 1275 | if (!shouldParseAsLightScript(file)) return; 1276 | 1277 | opts.parserOpts = opts.parserOpts || {}; 1278 | opts.parserOpts.parser = parse; 1279 | parserOpts.plugins.unshift("lightscript"); 1280 | // TODO: allow configuration options to disable these, as they slow down parsing 1281 | parserOpts.plugins.push("jsx", "flow"); 1282 | }, 1283 | 1284 | visitor: { 1285 | Program, 1286 | }, 1287 | 1288 | }; 1289 | } 1290 | -------------------------------------------------------------------------------- /src/stdlib.js: -------------------------------------------------------------------------------- 1 | 2 | export const lightscriptImports = { 3 | "looseEq": "inline", 4 | "looseNotEq": "inline", 5 | "bitwiseNot": "inline", 6 | "bitwiseAnd": "inline", 7 | "bitwiseOr": "inline", 8 | "bitwiseXor": "inline", 9 | "bitwiseLeftShift": "inline", 10 | "bitwiseRightShift": "inline", 11 | "bitwiseZeroFillRightShift": "inline", 12 | }; 13 | 14 | export const everyLodashMethod = [ 15 | "add", 16 | "after", 17 | "ary", 18 | "assign", 19 | "assignIn", 20 | "assignInWith", 21 | "assignWith", 22 | "at", 23 | "attempt", 24 | "before", 25 | "bind", 26 | "bindAll", 27 | "bindKey", 28 | "camelCase", 29 | "capitalize", 30 | "castArray", 31 | "ceil", 32 | "chain", 33 | "chunk", 34 | "clamp", 35 | "clone", 36 | "cloneDeep", 37 | "cloneDeepWith", 38 | "cloneWith", 39 | "compact", 40 | "concat", 41 | "cond", 42 | "conforms", 43 | "conformsTo", 44 | "constant", 45 | "countBy", 46 | "create", 47 | "curry", 48 | "curryRight", 49 | "debounce", 50 | "deburr", 51 | "defaultTo", 52 | "defaults", 53 | "defaultsDeep", 54 | "defer", 55 | "delay", 56 | "difference", 57 | "differenceBy", 58 | "differenceWith", 59 | "divide", 60 | "drop", 61 | "dropRight", 62 | "dropRightWhile", 63 | "dropWhile", 64 | "each", 65 | "eachRight", 66 | "endsWith", 67 | "entries", 68 | "entriesIn", 69 | "eq", 70 | "escape", 71 | "escapeRegExp", 72 | "every", 73 | "extend", 74 | "extendWith", 75 | "fill", 76 | "filter", 77 | "find", 78 | "findIndex", 79 | "findKey", 80 | "findLast", 81 | "findLastIndex", 82 | "findLastKey", 83 | "first", 84 | "flatMap", 85 | "flatMapDeep", 86 | "flatMapDepth", 87 | "flatten", 88 | "flattenDeep", 89 | "flattenDepth", 90 | "flip", 91 | "floor", 92 | "flow", 93 | "flowRight", 94 | "forEach", 95 | "forEachRight", 96 | "forIn", 97 | "forInRight", 98 | "forOwn", 99 | "forOwnRight", 100 | "fromPairs", 101 | "functions", 102 | "functionsIn", 103 | "get", 104 | "groupBy", 105 | "gt", 106 | "gte", 107 | "has", 108 | "hasIn", 109 | "head", 110 | "identity", 111 | "inRange", 112 | "includes", 113 | "indexOf", 114 | "initial", 115 | "intersection", 116 | "intersectionBy", 117 | "intersectionWith", 118 | "invert", 119 | "invertBy", 120 | "invoke", 121 | "invokeMap", 122 | "isArguments", 123 | "isArray", 124 | "isArrayBuffer", 125 | "isArrayLike", 126 | "isArrayLikeObject", 127 | "isBoolean", 128 | "isBuffer", 129 | "isDate", 130 | "isElement", 131 | "isEmpty", 132 | "isEqual", 133 | "isEqualWith", 134 | "isError", 135 | "isFinite", 136 | "isFunction", 137 | "isInteger", 138 | "isLength", 139 | "isMap", 140 | "isMatch", 141 | "isMatchWith", 142 | "isNaN", 143 | "isNative", 144 | "isNil", 145 | "isNull", 146 | "isNumber", 147 | "isObject", 148 | "isObjectLike", 149 | "isPlainObject", 150 | "isRegExp", 151 | "isSafeInteger", 152 | "isSet", 153 | "isString", 154 | "isSymbol", 155 | "isTypedArray", 156 | "isUndefined", 157 | "isWeakMap", 158 | "isWeakSet", 159 | "iteratee", 160 | "join", 161 | "kebabCase", 162 | "keyBy", 163 | "keys", 164 | "keysIn", 165 | "last", 166 | "lastIndexOf", 167 | "lowerCase", 168 | "lowerFirst", 169 | "lt", 170 | "lte", 171 | "map", 172 | "mapKeys", 173 | "mapValues", 174 | "matches", 175 | "matchesProperty", 176 | "max", 177 | "maxBy", 178 | "mean", 179 | "meanBy", 180 | "memoize", 181 | "merge", 182 | "mergeWith", 183 | "method", 184 | "methodOf", 185 | "min", 186 | "minBy", 187 | "mixin", 188 | "multiply", 189 | "negate", 190 | "noConflict", 191 | "noop", 192 | "now", 193 | "nth", 194 | "nthArg", 195 | "omit", 196 | "omitBy", 197 | "once", 198 | "orderBy", 199 | "over", 200 | "overArgs", 201 | "overEvery", 202 | "overSome", 203 | "pad", 204 | "padEnd", 205 | "padStart", 206 | "parseInt", 207 | "partial", 208 | "partialRight", 209 | "partition", 210 | "pick", 211 | "pickBy", 212 | "property", 213 | "propertyOf", 214 | "pull", 215 | "pullAll", 216 | "pullAllBy", 217 | "pullAllWith", 218 | "pullAt", 219 | "random", 220 | "range", 221 | "rangeRight", 222 | "rearg", 223 | "reduce", 224 | "reduceRight", 225 | "reject", 226 | "remove", 227 | "repeat", 228 | "replace", 229 | "rest", 230 | "result", 231 | "reverse", 232 | "round", 233 | "runInContext", 234 | "sample", 235 | "sampleSize", 236 | "set", 237 | "setWith", 238 | "shuffle", 239 | "size", 240 | "slice", 241 | "snakeCase", 242 | "some", 243 | "sortBy", 244 | "sortedIndex", 245 | "sortedIndexBy", 246 | "sortedIndexOf", 247 | "sortedLastIndex", 248 | "sortedLastIndexBy", 249 | "sortedLastIndexOf", 250 | "sortedUniq", 251 | "sortedUniqBy", 252 | "split", 253 | "spread", 254 | "startCase", 255 | "startsWith", 256 | "stubArray", 257 | "stubFalse", 258 | "stubObject", 259 | "stubString", 260 | "stubTrue", 261 | "subtract", 262 | "sum", 263 | "sumBy", 264 | "tail", 265 | "take", 266 | "takeRight", 267 | "takeRightWhile", 268 | "takeWhile", 269 | "tap", 270 | "template", 271 | "templateSettings", 272 | "throttle", 273 | "thru", 274 | "times", 275 | "toArray", 276 | "toFinite", 277 | "toInteger", 278 | "toLength", 279 | "toLower", 280 | "toNumber", 281 | "toPairs", 282 | "toPairsIn", 283 | "toPath", 284 | "toPlainObject", 285 | "toSafeInteger", 286 | "toString", 287 | "toUpper", 288 | "transform", 289 | "trim", 290 | "trimEnd", 291 | "trimStart", 292 | "truncate", 293 | "unary", 294 | "unescape", 295 | "union", 296 | "unionBy", 297 | "unionWith", 298 | "uniq", 299 | "uniqBy", 300 | "uniqWith", 301 | "uniqueId", 302 | "unset", 303 | "unzip", 304 | "unzipWith", 305 | "update", 306 | "updateWith", 307 | "upperCase", 308 | "upperFirst", 309 | "values", 310 | "valuesIn", 311 | "without", 312 | "words", 313 | "wrap", 314 | "xor", 315 | "xorBy", 316 | "xorWith", 317 | "zip", 318 | "zipObject", 319 | "zipObjectDeep", 320 | "zipWith", 321 | ]; 322 | 323 | export const lodashImports = everyLodashMethod.reduce((obj, methodName) => { 324 | obj[methodName] = "lodash"; 325 | return obj; 326 | }, {}); 327 | 328 | export const defaultImports = Object.assign({}, 329 | lightscriptImports, 330 | lodashImports, 331 | ); 332 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/async/actual.js: -------------------------------------------------------------------------------- 1 | () -/> 2 | await 1 3 | await 2 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/async/expected.js: -------------------------------------------------------------------------------- 1 | (async function () { 2 | await 1; 3 | return 2; 4 | }); -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/basic/actual.js: -------------------------------------------------------------------------------- 1 | () -> 2 | 1 3 | 2 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/basic/expected.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 1; 3 | return 2; 4 | }); 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/curly/actual.js: -------------------------------------------------------------------------------- 1 | () -> { 2 | 1 3 | 2 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/curly/expected.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 1; 3 | return 2; 4 | }); 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/fat-async/actual.js: -------------------------------------------------------------------------------- 1 | () =/> 2 | await 1 3 | await 2 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/fat-async/expected.js: -------------------------------------------------------------------------------- 1 | async () => { 2 | await 1; 3 | return 2; 4 | }; -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/fat-basic/actual.js: -------------------------------------------------------------------------------- 1 | () => 2 | 1 3 | 2 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/fat-basic/expected.js: -------------------------------------------------------------------------------- 1 | () => { 2 | 1; 3 | return 2; 4 | }; 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/fat-generator-void/actual.js: -------------------------------------------------------------------------------- 1 | for (const x of 2 | (): void =*> 3 | yield 1 4 | yield 2 5 | ) { 6 | console.log(x); 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/fat-generator-void/expected.js: -------------------------------------------------------------------------------- 1 | for (const x of function* (): void { 2 | yield 1; 3 | yield 2; 4 | }.bind(this)) { 5 | console.log(x); 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/fat-oneline/actual.js: -------------------------------------------------------------------------------- 1 | () => 1 2 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/fat-oneline/expected.js: -------------------------------------------------------------------------------- 1 | () => 1; 2 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/fat-twoline-unfortunate/actual.js: -------------------------------------------------------------------------------- 1 | () => 2 | 1 3 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/fat-twoline-unfortunate/expected.js: -------------------------------------------------------------------------------- 1 | () => { 2 | return 1; 3 | }; 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/fat-void/actual.js: -------------------------------------------------------------------------------- 1 | (): void => { 2 | 1 3 | 2 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/fat-void/expected.js: -------------------------------------------------------------------------------- 1 | (): void => { 2 | 1; 3 | 2; 4 | }; 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/generator-curly/actual.js: -------------------------------------------------------------------------------- 1 | () -*> { 2 | yield 1 3 | yield 2 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/generator-curly/expected.js: -------------------------------------------------------------------------------- 1 | (function* () { 2 | yield 1; 3 | return yield 2; 4 | }); 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/generator-void/actual.js: -------------------------------------------------------------------------------- 1 | (): void -*> 2 | yield 1 3 | yield 2 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/generator-void/expected.js: -------------------------------------------------------------------------------- 1 | (function* (): void { 2 | yield 1; 3 | yield 2; 4 | }); 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/generator/actual.js: -------------------------------------------------------------------------------- 1 | () -*> 2 | yield 1 3 | yield 2 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/generator/expected.js: -------------------------------------------------------------------------------- 1 | (function* () { 2 | yield 1; 3 | return yield 2; 4 | }); 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/one-param-no-paren-async/actual.js: -------------------------------------------------------------------------------- 1 | a -/> a 2 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/one-param-no-paren-async/expected.js: -------------------------------------------------------------------------------- 1 | (async function (a) { 2 | return a; 3 | }); 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/one-param-no-paren-fat/actual.js: -------------------------------------------------------------------------------- 1 | a => a 2 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/one-param-no-paren-fat/expected.js: -------------------------------------------------------------------------------- 1 | a => a; 2 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/one-param-no-paren/actual.js: -------------------------------------------------------------------------------- 1 | a -> a 2 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/one-param-no-paren/expected.js: -------------------------------------------------------------------------------- 1 | (function (a) { 2 | return a; 3 | }); 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/one-param-paren/actual.js: -------------------------------------------------------------------------------- 1 | (a) -> a 2 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/one-param-paren/expected.js: -------------------------------------------------------------------------------- 1 | (function (a) { 2 | return a; 3 | }); 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/oneline/actual.js: -------------------------------------------------------------------------------- 1 | () -> 1 2 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/oneline/expected.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | return 1; 3 | }); 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/void/actual.js: -------------------------------------------------------------------------------- 1 | (): void -> { 2 | 1 3 | 2 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-function-expressions/void/expected.js: -------------------------------------------------------------------------------- 1 | (function (): void { 2 | 1; 3 | 2; 4 | }); 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/computed-fat-generator/actual.js: -------------------------------------------------------------------------------- 1 | class A { 2 | ["f"]() =*> 3 | 1 4 | 2 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/computed-fat-generator/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | constructor() { 3 | this["f"] = this["f"].bind(this); 4 | } 5 | 6 | *["f"]() { 7 | 1; 8 | return 2; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/computed-skinny/actual.js: -------------------------------------------------------------------------------- 1 | class A { 2 | ["f"]() -> 3 | 1 4 | 2 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/computed-skinny/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | ["f"]() { 3 | 1; 4 | return 2; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-async/actual.js: -------------------------------------------------------------------------------- 1 | class A { 2 | f() =/> 3 | await this 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-async/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | constructor() { 3 | this.f = this.f.bind(this); 4 | } 5 | 6 | async f() { 7 | return this; 8 | } 9 | } -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-basic/actual.js: -------------------------------------------------------------------------------- 1 | class A { 2 | f() => 3 | this 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-basic/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | constructor() { 3 | this.f = this.f.bind(this); 4 | } 5 | 6 | f() { 7 | return this; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-extends-branched-super/actual.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | constructor() -> 3 | if false: 4 | super() 5 | foo() 6 | else: 7 | super() 8 | bar() 9 | 10 | f() => this 11 | } 12 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-extends-branched-super/expected.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | constructor() { 3 | if (false) { 4 | super(); 5 | this.f = this.f.bind(this); 6 | foo(); 7 | } else { 8 | super(); 9 | this.f = this.f.bind(this); 10 | bar(); 11 | } 12 | }f() { 13 | return this; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-extends-no-constructor/actual.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | f() => this 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-extends-no-constructor/expected.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | constructor(..._args) { 3 | super(..._args); 4 | this.f = this.f.bind(this); 5 | } 6 | 7 | f() { 8 | return this; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-extends-no-super/actual.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | constructor() -> 3 | foo() 4 | 5 | f() => this 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-extends-no-super/expected.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | constructor(..._args) { 3 | super(..._args); 4 | this.f = this.f.bind(this); 5 | 6 | foo(); 7 | }f() { 8 | return this; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-extends-super/actual.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | constructor() -> 3 | foo() 4 | super() 5 | bar() 6 | 7 | // don't be ugly, output! 8 | f() => this 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-extends-super/expected.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | constructor() { 3 | foo(); 4 | super(); 5 | this.f = this.f.bind(this); 6 | bar(); 7 | } // don't be ugly, output! 8 | f() { 9 | return this; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-generator/actual.js: -------------------------------------------------------------------------------- 1 | class A { 2 | f() =*> 3 | yield this 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-generator/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | constructor() { 3 | this.f = this.f.bind(this); 4 | } 5 | 6 | *f() { 7 | return yield this; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-nested-class-super/actual.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | constructor() -> 3 | class C extends B: 4 | constructor() -> 5 | super() 6 | 7 | f() => this 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-nested-class-super/expected.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | constructor(..._args) { 3 | super(..._args); 4 | this.f = this.f.bind(this); 5 | 6 | class C extends B { 7 | constructor() { 8 | super(); 9 | } 10 | } 11 | }f() { 12 | return this; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-static-declaration-computed/actual.js: -------------------------------------------------------------------------------- 1 | class A: 2 | static ["f"]() => 3 | 1 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-static-declaration-computed/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | static ["f"]() { 3 | return 1; 4 | } 5 | } 6 | A["f"] = A["f"].bind(A); 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-static-declaration/actual.js: -------------------------------------------------------------------------------- 1 | class A: 2 | static f() => 3 | 1 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-static-declaration/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | static f() { 3 | return 1; 4 | } 5 | } 6 | A.f = A.f.bind(A); 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-static-expression-assign-member/actual.js: -------------------------------------------------------------------------------- 1 | let obj = {} 2 | obj["klass"] = class A: 3 | static f() => 4 | 1 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-static-expression-assign-member/expected.js: -------------------------------------------------------------------------------- 1 | let obj = {}; 2 | obj["klass"] = class A { 3 | static f() { 4 | return 1; 5 | } 6 | }; 7 | obj["klass"].f = obj["klass"].f.bind(obj["klass"]); 8 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-static-expression-assign/actual.js: -------------------------------------------------------------------------------- 1 | let klass 2 | now klass = class A: 3 | static f() => 4 | 1 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-static-expression-assign/expected.js: -------------------------------------------------------------------------------- 1 | let klass; 2 | klass = class A { 3 | static f() { 4 | return 1; 5 | } 6 | }; 7 | klass.f = klass.f.bind(klass); 8 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-static-expression-var/actual.js: -------------------------------------------------------------------------------- 1 | klass = class A: 2 | static f() => 3 | 1 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-static-expression-var/expected.js: -------------------------------------------------------------------------------- 1 | const klass = class A { 2 | static f() { 3 | return 1; 4 | } 5 | }; 6 | klass.f = klass.f.bind(klass); 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-static-expression/actual.js: -------------------------------------------------------------------------------- 1 | x( 2 | class A: 3 | static f() => 4 | 1 5 | ) 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-static-expression/exec.js: -------------------------------------------------------------------------------- 1 | x(klass) -> 2 | f = klass.f 3 | f() 4 | 5 | name = x( 6 | class A: 7 | static f() => 8 | this.name 9 | ); 10 | 11 | assert.equal(name, "A"); 12 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-static-expression/expected.js: -------------------------------------------------------------------------------- 1 | var _class; 2 | 3 | x((_class = class A { 4 | static f() { 5 | return 1; 6 | } 7 | }, _class.f = _class.f.bind(_class), _class)); 8 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-with-constructor/actual.js: -------------------------------------------------------------------------------- 1 | class A { 2 | constructor() -> 3 | foo() 4 | 5 | // don't be ugly, output! 6 | f() => this 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/fat-with-constructor/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | constructor() { 3 | this.f = this.f.bind(this); 4 | 5 | foo(); 6 | } // don't be ugly, output! 7 | f() { 8 | return this; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-basic/actual.js: -------------------------------------------------------------------------------- 1 | class A { 2 | f() -> 3 | 1 4 | 2 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-basic/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | f() { 3 | 1; 4 | return 2; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-curly/actual.js: -------------------------------------------------------------------------------- 1 | class A { 2 | f() -> { 3 | 1 4 | 2 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-curly/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | f() { 3 | 1; 4 | return 2; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-extends-no-constructor/actual.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | f() -> 1 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-extends-no-constructor/expected.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | f() { 3 | return 1; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-extends-no-super-args/actual.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | constructor(x, y) -> 3 | foo(x, y) 4 | f() -> 1 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-extends-no-super-args/expected.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | constructor(x, y) { 3 | super(x, y); 4 | 5 | foo(x, y); 6 | }f() { 7 | return 1; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-extends-no-super/actual.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | constructor() -> 3 | foo() 4 | f() -> 1 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-extends-no-super/expected.js: -------------------------------------------------------------------------------- 1 | class A extends B { 2 | constructor(..._args) { 3 | super(..._args); 4 | 5 | foo(); 6 | }f() { 7 | return 1; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-get/actual.js: -------------------------------------------------------------------------------- 1 | class A { 2 | f() -get> 1 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-get/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | get f() { 3 | return 1; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-oneline/actual.js: -------------------------------------------------------------------------------- 1 | class A { 2 | f() -> 1 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-oneline/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | f() { 3 | return 1; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-set/actual.js: -------------------------------------------------------------------------------- 1 | class A { 2 | f(x) -set> 3 | this.x = x 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-set/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | set f(x) { 3 | this.x = x; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-static/actual.js: -------------------------------------------------------------------------------- 1 | class A: 2 | static f() -> 3 | 1 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-static/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | static f() { 3 | return 1; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-void/actual.js: -------------------------------------------------------------------------------- 1 | class A { 2 | f(): void -> { 3 | 1 4 | 2 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-class/skinny-void/expected.js: -------------------------------------------------------------------------------- 1 | class A { 2 | f(): void { 3 | 1; 4 | 2; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/computed-fat-generator/actual.js: -------------------------------------------------------------------------------- 1 | o = { 2 | ["f"]() =*> 3 | 1 4 | 2 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/computed-fat-generator/expected.js: -------------------------------------------------------------------------------- 1 | const o = { 2 | *["f"]() { 3 | 1; 4 | return 2; 5 | } 6 | }; 7 | o["f"] = o["f"].bind(o); 8 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/computed-skinny/actual.js: -------------------------------------------------------------------------------- 1 | o = { 2 | ["f"]() -> 3 | 1 4 | 2 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/computed-skinny/expected.js: -------------------------------------------------------------------------------- 1 | const o = { 2 | ["f"]() { 3 | 1; 4 | return 2; 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/fat-assign/actual.js: -------------------------------------------------------------------------------- 1 | let o 2 | now o = { 3 | f() => 4 | this 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/fat-assign/expected.js: -------------------------------------------------------------------------------- 1 | let o; 2 | o = { 3 | f() { 4 | return this; 5 | } 6 | }; 7 | o.f = o.f.bind(o); 8 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/fat-async/actual.js: -------------------------------------------------------------------------------- 1 | o = { 2 | f() =/> 3 | await this 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/fat-async/expected.js: -------------------------------------------------------------------------------- 1 | const o = { 2 | async f() { 3 | return this; 4 | } 5 | }; 6 | o.f = o.f.bind(o); -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/fat-basic/actual.js: -------------------------------------------------------------------------------- 1 | o = { 2 | f() => 3 | this 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/fat-basic/expected.js: -------------------------------------------------------------------------------- 1 | const o = { 2 | f() { 3 | return this; 4 | } 5 | }; 6 | o.f = o.f.bind(o); 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/fat-generator/actual.js: -------------------------------------------------------------------------------- 1 | o = { 2 | f() =*> 3 | yield this 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/fat-generator/expected.js: -------------------------------------------------------------------------------- 1 | const o = { 2 | *f() { 3 | return yield this; 4 | } 5 | }; 6 | o.f = o.f.bind(o); 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/fat-member/actual.js: -------------------------------------------------------------------------------- 1 | o.o = { 2 | f() => 3 | this 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/fat-member/expected.js: -------------------------------------------------------------------------------- 1 | o.o = { 2 | f() { 3 | return this; 4 | } 5 | }; 6 | o.o.f = o.o.f.bind(o.o); 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/fat-no-assign/actual.js: -------------------------------------------------------------------------------- 1 | x(a, { 2 | f() => 3 | this 4 | }, b) 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/fat-no-assign/expected.js: -------------------------------------------------------------------------------- 1 | var _obj; 2 | 3 | x(a, (_obj = { 4 | f() { 5 | return this; 6 | } 7 | }, _obj.f = _obj.f.bind(_obj), _obj), b); 8 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-async/actual.js: -------------------------------------------------------------------------------- 1 | o = { 2 | f(x) -/> 3 | await x 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-async/expected.js: -------------------------------------------------------------------------------- 1 | const o = { 2 | async f(x) { 3 | return x; 4 | } 5 | }; -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-basic/actual.js: -------------------------------------------------------------------------------- 1 | o = { 2 | f() -> 3 | 1 4 | 2 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-basic/expected.js: -------------------------------------------------------------------------------- 1 | const o = { 2 | f() { 3 | 1; 4 | return 2; 5 | } 6 | }; -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-curly/actual.js: -------------------------------------------------------------------------------- 1 | o = { 2 | f() -> { 3 | 1 4 | 2 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-curly/expected.js: -------------------------------------------------------------------------------- 1 | const o = { 2 | f() { 3 | 1; 4 | return 2; 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-generator/actual.js: -------------------------------------------------------------------------------- 1 | o = { 2 | f(x) -*> 3 | yield x 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-generator/expected.js: -------------------------------------------------------------------------------- 1 | const o = { 2 | *f(x) { 3 | return yield x; 4 | } 5 | }; -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-get/actual.js: -------------------------------------------------------------------------------- 1 | o = { 2 | f() -get> 1 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-get/expected.js: -------------------------------------------------------------------------------- 1 | const o = { 2 | get f() { 3 | return 1; 4 | } 5 | }; -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-oneline/actual.js: -------------------------------------------------------------------------------- 1 | o = { 2 | f() -> 1 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-oneline/expected.js: -------------------------------------------------------------------------------- 1 | const o = { 2 | f() { 3 | return 1; 4 | } 5 | }; -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-set/actual.js: -------------------------------------------------------------------------------- 1 | o = { 2 | f(x) -set> 3 | this.x = x 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-set/expected.js: -------------------------------------------------------------------------------- 1 | const o = { 2 | set f(x) { 3 | this.x = x; 4 | } }; -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-void/actual.js: -------------------------------------------------------------------------------- 1 | o = { 2 | f(): void -> { 3 | 1 4 | 2 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/fixtures/arrow-methods-obj/skinny-void/expected.js: -------------------------------------------------------------------------------- 1 | const o = { 2 | f(): void { 3 | 1; 4 | 2; 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /test/fixtures/await-arrow/assign-member/actual.js: -------------------------------------------------------------------------------- 1 | fn() -/> 2 | x.y <- fetch() 3 | -------------------------------------------------------------------------------- /test/fixtures/await-arrow/assign-member/expected.js: -------------------------------------------------------------------------------- 1 | async function fn() { 2 | return x.y = await fetch(); 3 | } -------------------------------------------------------------------------------- /test/fixtures/await-arrow/assign-pattern/actual.js: -------------------------------------------------------------------------------- 1 | fn() -/> 2 | {x, xx: {xxx}} <- fetch() 3 | [y, [yy]] <- fetch() 4 | x + y 5 | -------------------------------------------------------------------------------- /test/fixtures/await-arrow/assign-pattern/expected.js: -------------------------------------------------------------------------------- 1 | async function fn() { 2 | const { x, xx: { xxx } } = await fetch(); 3 | const [y, [yy]] = await fetch(); 4 | return x + y; 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/await-arrow/assign/actual.js: -------------------------------------------------------------------------------- 1 | fn() -/> 2 | x <- fetch() 3 | x + 1 4 | -------------------------------------------------------------------------------- /test/fixtures/await-arrow/assign/expected.js: -------------------------------------------------------------------------------- 1 | async function fn() { 2 | const x = await fetch(); 3 | return x + 1; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/await-arrow/await-array/actual.js: -------------------------------------------------------------------------------- 1 | fn() -/> 2 | x <- [p1, p2] 3 | const y = await [p1, p2] 4 | <- [for const p of ps: p] 5 | -------------------------------------------------------------------------------- /test/fixtures/await-arrow/await-array/expected.js: -------------------------------------------------------------------------------- 1 | async function fn() { 2 | const x = await Promise.all([p1, p2]); 3 | const y = await Promise.all([p1, p2]); 4 | return Promise.all((() => { 5 | const _arr = []; 6 | for (const p of ps) _arr.push(p);return _arr; 7 | })()); 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/await-arrow/safe-assign/actual.js: -------------------------------------------------------------------------------- 1 | fn() -/> 2 | x { 3 | try { 4 | return await fetch(); 5 | } catch (_err) { 6 | return _err; 7 | } 8 | })(); 9 | return x + 1; 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/await-arrow/safe-statement/actual.js: -------------------------------------------------------------------------------- 1 | fn() -/> 2 | { 3 | try { 4 | return await fetch(); 5 | } catch (_err) { 6 | return _err; 7 | } 8 | })(); 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/await-arrow/statement/actual.js: -------------------------------------------------------------------------------- 1 | fn() -/> 2 | <- fetch() 3 | -------------------------------------------------------------------------------- /test/fixtures/await-arrow/statement/expected.js: -------------------------------------------------------------------------------- 1 | async function fn() { 2 | return fetch(); 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/assignment-expr/actual.js: -------------------------------------------------------------------------------- 1 | [for idx i in Array(10): 2 | now x = f(i) 3 | ] 4 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/assignment-expr/exec.js: -------------------------------------------------------------------------------- 1 | let x = 0 2 | result = [for idx i in Array(10): 3 | now x = i 4 | ] 5 | assert.deepEqual(result, [0,1,2,3,4,5,6,7,8,9]) 6 | assert(x === 9) 7 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/assignment-expr/expected.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | const _arr = []; 3 | 4 | for (let _arr2 = Array(10), i = 0, _len = _arr2.length; i < _len; i++) { 5 | _arr.push(x = f(i)); 6 | } 7 | 8 | return _arr; 9 | })(); -------------------------------------------------------------------------------- /test/fixtures/comprehensions/await/actual.js: -------------------------------------------------------------------------------- 1 | f() -/> 2 | <- [for now x of arr: 3 | <- x 4 | ] 5 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/await/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "`await` is not allowed within Comprehensions; instead, await the Comprehension (eg; `y <- [for x of xs: x]`)." 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/closure-nested-deep/actual.js: -------------------------------------------------------------------------------- 1 | [for idx i in Array(10): 2 | for idx j in a: 3 | if i < 5: 4 | f() -> 5 | {for idx k in Array(10): 6 | if k > 7: 7 | k, g() -> function h() { [i,j,k] } 8 | } 9 | ] 10 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/closure-nested-deep/expected.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | const _arr = []; 3 | 4 | for (let _arr2 = Array(10), i = 0, _len = _arr2.length; i < _len; i++) { 5 | for (let j = 0, _len2 = a.length; j < _len2; j++) { 6 | if (i < 5) { 7 | function f() { 8 | return (() => { 9 | const _obj = {}; 10 | 11 | for (let _arr3 = Array(10), k = 0, _len3 = _arr3.length; k < _len3; k++) { 12 | if (k > 7) { 13 | _obj[k] = function g() { 14 | return function h() { 15 | return [i, j, k]; 16 | }; 17 | }; 18 | } 19 | } 20 | 21 | return _obj; 22 | })(); 23 | } 24 | 25 | _arr.push(f); 26 | } 27 | } 28 | } 29 | 30 | return _arr; 31 | })(); -------------------------------------------------------------------------------- /test/fixtures/comprehensions/closure-nested-semantic.js: -------------------------------------------------------------------------------- 1 | closures = [ for idx i in Array(10): f() -> g() -> i ] 2 | closureResults = [ for elem f in closures: f()() ] 3 | 4 | assert.deepEqual(closureResults, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 5 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/closure-nested/actual.js: -------------------------------------------------------------------------------- 1 | [ for idx i in Array(10): f() -> g() -> i ] 2 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/closure-nested/expected.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | const _arr = []; 3 | 4 | for (let _arr2 = Array(10), i = 0, _len = _arr2.length; i < _len; i++) { 5 | function f() { 6 | return function g() { 7 | return i; 8 | }; 9 | } 10 | 11 | _arr.push(f); 12 | } 13 | 14 | return _arr; 15 | })(); -------------------------------------------------------------------------------- /test/fixtures/comprehensions/closure-semantic.js: -------------------------------------------------------------------------------- 1 | closures = [ for idx i in Array(10): f() -> i ] 2 | closureResults = [ for elem f in closures: f() ] 3 | 4 | assert.deepEqual(closureResults, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 5 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/closure/actual.js: -------------------------------------------------------------------------------- 1 | [ for idx i in Array(10): f() -> i ] 2 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/closure/expected.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | const _arr = []; 3 | 4 | for (let _arr2 = Array(10), i = 0, _len = _arr2.length; i < _len; i++) { 5 | function f() { 6 | return i; 7 | } 8 | 9 | _arr.push(f); 10 | } 11 | 12 | return _arr; 13 | })(); -------------------------------------------------------------------------------- /test/fixtures/comprehensions/declared-inner-function-semantic.js: -------------------------------------------------------------------------------- 1 | closures = [for idx i in Array(3): 2 | x = g(i) 3 | g(x) -> x+i 4 | ] 5 | results = [for elem f in closures: f(1)] 6 | 7 | assert.deepEqual(results, [1,2,3]) 8 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/declared-inner-function/actual.js: -------------------------------------------------------------------------------- 1 | closures = [for idx i in Array(3): 2 | x = g(i) 3 | g(x) -> x+1 4 | ] 5 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/declared-inner-function/expected.js: -------------------------------------------------------------------------------- 1 | const closures = (() => { 2 | const _arr = []; 3 | 4 | for (let _arr2 = Array(3), i = 0, _len = _arr2.length; i < _len; i++) { 5 | const x = g(i); 6 | 7 | function g(x) { 8 | return x + 1; 9 | } 10 | 11 | _arr.push(g); 12 | } 13 | 14 | return _arr; 15 | })(); -------------------------------------------------------------------------------- /test/fixtures/comprehensions/from.js: -------------------------------------------------------------------------------- 1 | arr = [4, 5, 6] 2 | 3 | c = [ for idx i, elem x in arr: [i, x] ] 4 | assert.deepEqual(c, [[0, 4], [1, 5], [2, 6]]) 5 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/if-elif.js: -------------------------------------------------------------------------------- 1 | c = [ for let i=0; i<10; i++: if i > 5: i elif i > 3: i * 2 ] 2 | assert.deepEqual(c, [8, 10, 6, 7, 8, 9]) 3 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/if-else-if.js: -------------------------------------------------------------------------------- 1 | c = [ for let i=0; i<10; i++: if i > 5: i else if i > 3: i * 2 ] 2 | assert.deepEqual(c, [8, 10, 6, 7, 8, 9]) 3 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/if-else.js: -------------------------------------------------------------------------------- 1 | c = [ for let i=0; i<10; i++: if i > 5: i else: 0 ] 2 | assert.deepEqual(c, [0, 0, 0, 0, 0, 0, 6, 7, 8, 9]) 3 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/if.js: -------------------------------------------------------------------------------- 1 | c = [ for let i=0; i<10; i++: if i > 5: i ] 2 | assert.deepEqual(c, [6, 7, 8, 9]) 3 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/in.js: -------------------------------------------------------------------------------- 1 | arr = [4, 5, 6] 2 | 3 | x = [ for const i in arr: parseInt(i) ] 4 | assert.deepEqual(x, [0, 1, 2]) 5 | 6 | y = [ for const i in arr: parseInt(i) + 1 ] 7 | assert.deepEqual(y, [1, 2, 3]) 8 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/multiple-for.js: -------------------------------------------------------------------------------- 1 | c = [ for let i=0;i<3;i++: for let j=5;j<7;j++: [i, j] ] 2 | assert.deepEqual(c, [ [0, 5], [0, 6], [1, 5], [1, 6], [2, 5], [2, 6] ]) 3 | 4 | d = [ for let i=0;i<3;i++: for let j=5;j<7;j++: if i > 1: [i, j] ] 5 | assert.deepEqual(d, [ [2, 5], [2, 6] ]) 6 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/nested.js: -------------------------------------------------------------------------------- 1 | c = [ for let i=0; i<4; i++: [ for let i=0; i<3; i++: 2 ] ] 2 | assert.deepEqual(c, [ [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2] ]) 3 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/object-basic/actual.js: -------------------------------------------------------------------------------- 1 | {for elem x in arr: (x, f(x))} 2 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/object-basic/expected.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | const _obj = {}; 3 | 4 | for (let _i = 0, _len = arr.length; _i < _len; _i++) { 5 | const x = arr[_i]; 6 | _obj[x] = f(x); 7 | } 8 | 9 | return _obj; 10 | })(); -------------------------------------------------------------------------------- /test/fixtures/comprehensions/object-declared-inner-function/actual.js: -------------------------------------------------------------------------------- 1 | {for idx i in Array(3): 2 | x = g(i) 3 | i, g(x) -> x+1 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/object-declared-inner-function/expected.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | const _obj = {}; 3 | 4 | for (let _arr = Array(3), i = 0, _len = _arr.length; i < _len; i++) { 5 | const x = g(i); 6 | 7 | _obj[i] = function g(x) { 8 | return x + 1; 9 | }; 10 | } 11 | 12 | return _obj; 13 | })(); -------------------------------------------------------------------------------- /test/fixtures/comprehensions/object-if.js: -------------------------------------------------------------------------------- 1 | obj = {for idx i in Array(10): if i > 8: (i, i)} 2 | 3 | assert.deepEqual(obj, { "9": 9 }) 4 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/object-malformed-expr-1/actual.js: -------------------------------------------------------------------------------- 1 | {for elem x in arr: 1} 2 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/object-malformed-expr-1/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "Object comprehensions must end with a (key, value) pair." 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/object-malformed-expr-2/actual.js: -------------------------------------------------------------------------------- 1 | {for elem x in arr: a, b, c} 2 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/object-malformed-expr-2/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "Object comprehensions must end with a (key, value) pair." 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/object-nested.js: -------------------------------------------------------------------------------- 1 | obj = { for idx i in Array(3): for idx j in Array(2): if i < 2: `${i}*${j}`, i*j } 2 | 3 | assert.deepEqual(obj, {"0*0": 0, "0*1": 0, "1*0": 0, "1*1": 1}) 4 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/object-no-parens/actual.js: -------------------------------------------------------------------------------- 1 | {for elem x in arr: x, f(x)} 2 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/object-no-parens/expected.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | const _obj = {}; 3 | 4 | for (let _i = 0, _len = arr.length; _i < _len; _i++) { 5 | const x = arr[_i]; 6 | _obj[x] = f(x); 7 | } 8 | 9 | return _obj; 10 | })(); -------------------------------------------------------------------------------- /test/fixtures/comprehensions/object.js: -------------------------------------------------------------------------------- 1 | obj = {for elem e in [1,2,3]: e, 2*e} 2 | 3 | assert.deepEqual(obj, { "1": 2, "2": 4, "3": 6}) 4 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/of.js: -------------------------------------------------------------------------------- 1 | arr = [4, 5, 6] 2 | 3 | x = [ for const x of arr: x ] 4 | assert.deepEqual(x, [4, 5, 6]) 5 | 6 | y = [ for const y of arr: y + 1 ] 7 | assert.deepEqual(y, [5, 6, 7]) 8 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/return-inside-fn/actual.js: -------------------------------------------------------------------------------- 1 | f() -> 2 | c = [for const x of arr: 3 | g() -> return x 4 | ] 5 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/return-inside-fn/expected.js: -------------------------------------------------------------------------------- 1 | function f() { 2 | const c = (() => { 3 | const _arr = []; 4 | for (const x of arr) { 5 | function g() { 6 | return x; 7 | } 8 | 9 | _arr.push(g); 10 | }return _arr; 11 | })(); 12 | return c; 13 | } -------------------------------------------------------------------------------- /test/fixtures/comprehensions/return/actual.js: -------------------------------------------------------------------------------- 1 | arr = [4, 5, 6] 2 | 3 | f() -> 4 | c = [ for now x of arr: 5 | if x == 4: return 6 | x 7 | ] 8 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/return/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "`return` is not allowed within Comprehensions." 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/semi.js: -------------------------------------------------------------------------------- 1 | arr = [4, 5, 6] 2 | 3 | c = [ for let i = 0; i < arr.length; i++: [i, arr[i]] ] 4 | assert.deepEqual(c, [[0, 4], [1, 5], [2, 6]]) 5 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/variable-decl/actual.js: -------------------------------------------------------------------------------- 1 | [for idx i in Array(10): 2 | x = f(i) 3 | ] 4 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/variable-decl/expected.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | const _arr = []; 3 | 4 | for (let _arr2 = Array(10), i = 0, _len = _arr2.length; i < _len; i++) { 5 | const x = f(i); 6 | 7 | _arr.push(x) 8 | } 9 | 10 | return _arr; 11 | })(); -------------------------------------------------------------------------------- /test/fixtures/comprehensions/yield/actual.js: -------------------------------------------------------------------------------- 1 | arr = [4, 5, 6] 2 | 3 | f() -*> 4 | c = [ for now x of arr: yield x ] 5 | -------------------------------------------------------------------------------- /test/fixtures/comprehensions/yield/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "`yield` is not allowed within Comprehensions." 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/examples/fizzbuzz.js: -------------------------------------------------------------------------------- 1 | 2 | fizzBuzz(n = 100) -> 3 | arr = [] 4 | for let i = 1; i < n+1; i++: 5 | x = 6 | if i % 3 == 0 and i % 5 == 0: 7 | "fizzbuzz" 8 | elif i % 3 == 0: 9 | "fizz" 10 | elif i % 5 == 0: 11 | "buzz" 12 | else: 13 | i 14 | arr.push(x) 15 | arr 16 | 17 | fizzBuzzComp(n = 100) -> 18 | [for let i = 1; i < n+1; i++: 19 | if i % 3 == 0 and i % 5 == 0: 20 | "fizzbuzz" 21 | elif i % 3 == 0: 22 | "fizz" 23 | elif i % 5 == 0: 24 | "buzz" 25 | else: 26 | i 27 | ] 28 | 29 | fizzBuzzMap(n = 100) -> 30 | Array(n+1).fill(0) 31 | .map((x, i) -> i) 32 | .filter(x -> x != 0) 33 | .map(x -> 34 | if x % 3 == 0 and x % 5 == 0: 35 | "fizzbuzz" 36 | elif x % 3 == 0: 37 | "fizz" 38 | elif x % 5 == 0: 39 | "buzz" 40 | else: 41 | x 42 | ) 43 | 44 | fizzBuzzMap2(n = 100) -> 45 | [for let i = 1; i < n+1; i++: i].map(x -> 46 | if x % 3 == 0 and x % 5 == 0: "fizzbuzz" 47 | elif x % 3 == 0: "fizz" 48 | elif x % 5 == 0: "buzz" 49 | else: x 50 | ) 51 | 52 | fizzBuzzGen(n = 100) -*> 53 | for let i = 1; i < n+1; i++: 54 | if i % 3 == 0 and i % 5 == 0: 55 | yield "fizzbuzz" 56 | elif i % 3 == 0: 57 | yield "fizz" 58 | elif i % 5 == 0: 59 | yield "buzz" 60 | else: 61 | yield i 62 | 63 | assert.deepEqual(fizzBuzz(), [1, 2, "fizz", 4, "buzz", "fizz", 7, 8, "fizz", "buzz", 11, "fizz", 13, 14, "fizzbuzz", 16, 17, "fizz", 19, "buzz", "fizz", 22, 23, "fizz", "buzz", 26, "fizz", 28, 29, "fizzbuzz", 31, 32, "fizz", 34, "buzz", "fizz", 37, 38, "fizz", "buzz", 41, "fizz", 43, 44, "fizzbuzz", 46, 47, "fizz", 49, "buzz", "fizz", 52, 53, "fizz", "buzz", 56, "fizz", 58, 59, "fizzbuzz", 61, 62, "fizz", 64, "buzz", "fizz", 67, 68, "fizz", "buzz", 71, "fizz", 73, 74, "fizzbuzz", 76, 77, "fizz", 79, "buzz", "fizz", 82, 83, "fizz", "buzz", 86, "fizz", 88, 89, "fizzbuzz", 91, 92, "fizz", 94, "buzz", "fizz", 97, 98, "fizz", "buzz"]); 64 | assert.deepEqual(fizzBuzzComp(), [1, 2, "fizz", 4, "buzz", "fizz", 7, 8, "fizz", "buzz", 11, "fizz", 13, 14, "fizzbuzz", 16, 17, "fizz", 19, "buzz", "fizz", 22, 23, "fizz", "buzz", 26, "fizz", 28, 29, "fizzbuzz", 31, 32, "fizz", 34, "buzz", "fizz", 37, 38, "fizz", "buzz", 41, "fizz", 43, 44, "fizzbuzz", 46, 47, "fizz", 49, "buzz", "fizz", 52, 53, "fizz", "buzz", 56, "fizz", 58, 59, "fizzbuzz", 61, 62, "fizz", 64, "buzz", "fizz", 67, 68, "fizz", "buzz", 71, "fizz", 73, 74, "fizzbuzz", 76, 77, "fizz", 79, "buzz", "fizz", 82, 83, "fizz", "buzz", 86, "fizz", 88, 89, "fizzbuzz", 91, 92, "fizz", 94, "buzz", "fizz", 97, 98, "fizz", "buzz"]); 65 | assert.deepEqual(fizzBuzzMap(), [1, 2, "fizz", 4, "buzz", "fizz", 7, 8, "fizz", "buzz", 11, "fizz", 13, 14, "fizzbuzz", 16, 17, "fizz", 19, "buzz", "fizz", 22, 23, "fizz", "buzz", 26, "fizz", 28, 29, "fizzbuzz", 31, 32, "fizz", 34, "buzz", "fizz", 37, 38, "fizz", "buzz", 41, "fizz", 43, 44, "fizzbuzz", 46, 47, "fizz", 49, "buzz", "fizz", 52, 53, "fizz", "buzz", 56, "fizz", 58, 59, "fizzbuzz", 61, 62, "fizz", 64, "buzz", "fizz", 67, 68, "fizz", "buzz", 71, "fizz", 73, 74, "fizzbuzz", 76, 77, "fizz", 79, "buzz", "fizz", 82, 83, "fizz", "buzz", 86, "fizz", 88, 89, "fizzbuzz", 91, 92, "fizz", 94, "buzz", "fizz", 97, 98, "fizz", "buzz"]); 66 | assert.deepEqual(fizzBuzzMap(), [1, 2, "fizz", 4, "buzz", "fizz", 7, 8, "fizz", "buzz", 11, "fizz", 13, 14, "fizzbuzz", 16, 17, "fizz", 19, "buzz", "fizz", 22, 23, "fizz", "buzz", 26, "fizz", 28, 29, "fizzbuzz", 31, 32, "fizz", 34, "buzz", "fizz", 37, 38, "fizz", "buzz", 41, "fizz", 43, 44, "fizzbuzz", 46, 47, "fizz", 49, "buzz", "fizz", 52, 53, "fizz", "buzz", 56, "fizz", 58, 59, "fizzbuzz", 61, 62, "fizz", 64, "buzz", "fizz", 67, 68, "fizz", "buzz", 71, "fizz", 73, 74, "fizzbuzz", 76, 77, "fizz", 79, "buzz", "fizz", 82, 83, "fizz", "buzz", 86, "fizz", 88, 89, "fizzbuzz", 91, 92, "fizz", 94, "buzz", "fizz", 97, 98, "fizz", "buzz"]); 67 | assert.deepEqual([for const x of fizzBuzzGen(): x], [1, 2, "fizz", 4, "buzz", "fizz", 7, 8, "fizz", "buzz", 11, "fizz", 13, 14, "fizzbuzz", 16, 17, "fizz", 19, "buzz", "fizz", 22, 23, "fizz", "buzz", 26, "fizz", 28, 29, "fizzbuzz", 31, 32, "fizz", 34, "buzz", "fizz", 37, 38, "fizz", "buzz", 41, "fizz", 43, 44, "fizzbuzz", 46, 47, "fizz", 49, "buzz", "fizz", 52, 53, "fizz", "buzz", 56, "fizz", 58, 59, "fizzbuzz", 61, 62, "fizz", 64, "buzz", "fizz", 67, 68, "fizz", "buzz", 71, "fizz", 73, 74, "fizzbuzz", 76, 77, "fizz", 79, "buzz", "fizz", 82, 83, "fizz", "buzz", 86, "fizz", 88, 89, "fizzbuzz", 91, 92, "fizz", 94, "buzz", "fizz", 97, 98, "fizz", "buzz"]); 68 | -------------------------------------------------------------------------------- /test/fixtures/examples/jsx/actual.js: -------------------------------------------------------------------------------- 1 | otherCondition() -> true 2 | 3 | ThingsList1({ things, selectedId }) => 4 |
    5 | {[for const thing of things: 6 | if thing.id == selectedId and otherCondition(): 7 | 8 | else: 9 | 10 | ]} 11 |
12 | 13 | ThingsList2({ things, selectedId }) => 14 |
    15 | {things.map(thing -> 16 | if thing.id == selectedId and otherCondition(): 17 | 18 | else: 19 | 20 | )} 21 |
22 | 23 | 24 | ThingsList3({ things, selectedId }) => 25 |
    26 | {[ 27 | for elem thing in things { 28 | if thing.id == selectedId and otherCondition() { 29 | 30 | } else { 31 | 32 | } 33 | } 34 | ]} 35 |
36 | -------------------------------------------------------------------------------- /test/fixtures/examples/jsx/expected.js: -------------------------------------------------------------------------------- 1 | function otherCondition() { 2 | return true; 3 | } 4 | 5 | const ThingsList1 = ({ things, selectedId }) => { 6 | return
    7 | {(() => { 8 | const _arr = []; 9 | for (const thing of things) { 10 | if (thing.id === selectedId && otherCondition()) { 11 | _arr.push(); 12 | } else { 13 | _arr.push(); 14 | } 15 | }return _arr; 16 | })()} 17 |
; 18 | }; 19 | 20 | const ThingsList2 = ({ things, selectedId }) => { 21 | return
    22 | {things.map(function (thing) { 23 | if (thing.id === selectedId && otherCondition()) { 24 | return ; 25 | } else { 26 | return ; 27 | } 28 | })} 29 |
; 30 | }; 31 | 32 | const ThingsList3 = ({ things, selectedId }) => { 33 | return
    34 | {(() => { 35 | const _arr2 = []; 36 | 37 | for (let _i = 0, _len = things.length; _i < _len; _i++) { 38 | const thing = things[_i]; 39 | 40 | if (thing.id === selectedId && otherCondition()) { 41 | _arr2.push(); 42 | } else { 43 | _arr2.push(); 44 | } 45 | } 46 | 47 | return _arr2; 48 | })()} 49 |
; 50 | }; -------------------------------------------------------------------------------- /test/fixtures/for-in/array-elem-idx.js: -------------------------------------------------------------------------------- 1 | x = [] 2 | for elem e, idx i in [4, 5, 6]: x.push([i, e]) 3 | assert.deepEqual(x, [[0, 4], [1, 5], [2, 6]]) 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/array-elem.js: -------------------------------------------------------------------------------- 1 | x = [] 2 | for elem e in [4, 5, 6]: x.push(e) 3 | assert.deepEqual(x, [4, 5, 6]) 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/array-identifier/actual.js: -------------------------------------------------------------------------------- 1 | for elem e in arr: e 2 | -------------------------------------------------------------------------------- /test/fixtures/for-in/array-identifier/expected.js: -------------------------------------------------------------------------------- 1 | for (let _i = 0, _len = arr.length; _i < _len; _i++) { 2 | const e = arr[_i]; 3 | e; 4 | } -------------------------------------------------------------------------------- /test/fixtures/for-in/array-idx-elem.js: -------------------------------------------------------------------------------- 1 | x = [] 2 | for idx i, elem e in [4, 5, 6]: x.push([i, e]) 3 | assert.deepEqual(x, [[0, 4], [1, 5], [2, 6]]) 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/array-idx.js: -------------------------------------------------------------------------------- 1 | x = [] 2 | for idx i in [4, 5, 6]: x.push(i) 3 | assert.deepEqual(x, [0, 1, 2]) 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/array-scope-ordering/actual.js: -------------------------------------------------------------------------------- 1 | f() -> 2 | sideEffect0() 3 | for elem k1 in sideEffect1(): k1 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/array-scope-ordering/expected.js: -------------------------------------------------------------------------------- 1 | function f() { 2 | sideEffect0(); 3 | 4 | for (let _arr = sideEffect1(), _i = 0, _len = _arr.length; _i < _len; _i++) { 5 | const k1 = _arr[_i]; 6 | k1; 7 | } 8 | } -------------------------------------------------------------------------------- /test/fixtures/for-in/array-scope-register-declaration/actual.js: -------------------------------------------------------------------------------- 1 | f() -> 2 | for elem k in g(): k 3 | for elem k in g(): k 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/array-scope-register-declaration/expected.js: -------------------------------------------------------------------------------- 1 | function f() { 2 | for (let _arr = g(), _i = 0, _len = _arr.length; _i < _len; _i++) { 3 | const k = _arr[_i]; 4 | k; 5 | } 6 | 7 | for (let _arr2 = g(), _i2 = 0, _len2 = _arr2.length; _i2 < _len2; _i2++) { 8 | const k = _arr2[_i2]; 9 | k; 10 | } 11 | } -------------------------------------------------------------------------------- /test/fixtures/for-in/assign-enhanced-in-without-now/actual.js: -------------------------------------------------------------------------------- 1 | for key k, val v in (obj = complexFunction()) {} 2 | -------------------------------------------------------------------------------- /test/fixtures/for-in/assign-enhanced-in-without-now/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "Incorrect assignment: to reassign, use `now`; to assign as `const`, put on its own line." 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/assign-enhanced-in/actual.js: -------------------------------------------------------------------------------- 1 | // _obj tests for scope uniqueness 2 | for key k, val v in (now _obj = complexFunction()) {} 3 | -------------------------------------------------------------------------------- /test/fixtures/for-in/assign-enhanced-in/expected.js: -------------------------------------------------------------------------------- 1 | // _obj tests for scope uniqueness 2 | for (let _obj2 = _obj = complexFunction(), _i = 0, _keys = Object.keys(_obj2), _len = _keys.length; _i < _len; _i++) { 3 | const k = _keys[_i]; 4 | const v = _obj2[k]; 5 | } -------------------------------------------------------------------------------- /test/fixtures/for-in/assign-in-without-now/actual.js: -------------------------------------------------------------------------------- 1 | for (const k in (obj = complexFunction())) {} 2 | -------------------------------------------------------------------------------- /test/fixtures/for-in/assign-in-without-now/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "Incorrect assignment: to reassign, use `now`; to assign as `const`, put on its own line." 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/assign-in/actual.js: -------------------------------------------------------------------------------- 1 | for (const k in (now obj = complexFunction())) {} 2 | -------------------------------------------------------------------------------- /test/fixtures/for-in/assign-in/expected.js: -------------------------------------------------------------------------------- 1 | for (const k in obj = complexFunction()) {} -------------------------------------------------------------------------------- /test/fixtures/for-in/elem-var-shadowing/actual.js: -------------------------------------------------------------------------------- 1 | for elem e in []: 2 | if true: 3 | e = 7 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/elem-var-shadowing/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "`e` is shadowed from a higher scope" 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/evaluate-expr-once/actual.js: -------------------------------------------------------------------------------- 1 | for key k, val v in slowRunningFunction(): k 2 | -------------------------------------------------------------------------------- /test/fixtures/for-in/evaluate-expr-once/expected.js: -------------------------------------------------------------------------------- 1 | for (let _obj = slowRunningFunction(), _i = 0, _keys = Object.keys(_obj), _len = _keys.length; _i < _len; _i++) { 2 | const k = _keys[_i]; 3 | const v = _obj[k]; 4 | k; 5 | } -------------------------------------------------------------------------------- /test/fixtures/for-in/if/actual.js: -------------------------------------------------------------------------------- 1 | for idx i in Array(10): for idx j in Array(10): if i > 3: i 2 | -------------------------------------------------------------------------------- /test/fixtures/for-in/if/expected.js: -------------------------------------------------------------------------------- 1 | for (let _arr = Array(10), i = 0, _len = _arr.length; i < _len; i++) { 2 | for (let _arr2 = Array(10), j = 0, _len2 = _arr2.length; j < _len2; j++) { 3 | if (i > 3) i; 4 | } 5 | } -------------------------------------------------------------------------------- /test/fixtures/for-in/nested-semantic.js: -------------------------------------------------------------------------------- 1 | arr1 = [0,1] 2 | objExpr2() -> ({ key: "key" }) 3 | arrExpr3() -> [2,3] 4 | obj4 = { key1: "value1", key2: "value2" } 5 | 6 | result = [for elem i in arr1: for key k in objExpr2(): for idx j in arrExpr3(): for val l in obj4: [i,j,k,l]] 7 | 8 | assert.deepEqual(result, [ 9 | [0, 0, "key", "value1"], 10 | [0, 0, "key", "value2"], 11 | [0, 1, "key", "value1"], 12 | [0, 1, "key", "value2"], 13 | [1, 0, "key", "value1"], 14 | [1, 0, "key", "value2"], 15 | [1, 1, "key", "value1"], 16 | [1, 1, "key", "value2"] 17 | ]) 18 | -------------------------------------------------------------------------------- /test/fixtures/for-in/nested/actual.js: -------------------------------------------------------------------------------- 1 | for elem i in arr1: for key k in objExpr2(): for idx j in arrExpr3(): for val l in obj4: [i,j,k,l] 2 | -------------------------------------------------------------------------------- /test/fixtures/for-in/nested/expected.js: -------------------------------------------------------------------------------- 1 | for (let _i = 0, _len = arr1.length; _i < _len; _i++) { 2 | const i = arr1[_i]; 3 | 4 | for (let _obj = objExpr2(), _i2 = 0, _keys = Object.keys(_obj), _len2 = _keys.length; _i2 < _len2; _i2++) { 5 | const k = _keys[_i2]; 6 | 7 | for (let _arr = arrExpr3(), j = 0, _len3 = _arr.length; j < _len3; j++) { 8 | for (let _i3 = 0, _keys2 = Object.keys(obj4), _len4 = _keys2.length; _i3 < _len4; _i3++) { 9 | const _k = _keys2[_i3]; 10 | const l = obj4[_k]; 11 | [i, j, k, l]; 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /test/fixtures/for-in/not-prefixed/actual.js: -------------------------------------------------------------------------------- 1 | for k in obj: k 2 | -------------------------------------------------------------------------------- /test/fixtures/for-in/not-prefixed/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "for-in requires a variable qualifier: `now` to reassign an existing variable, or `const`, `let`, `var` to declare a new one. Use `idx` or `elem` to iterate an array. Use `key` or `val` to iterate an object. (1:4)" 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/obj-key-val.js: -------------------------------------------------------------------------------- 1 | x = [] 2 | for key k, val v in { one: 2, three: 4, five: 6 }: x.push([k,v]) 3 | assert.deepEqual(x, [["one", 2], ["three", 4], ["five", 6]]) 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/obj-key.js: -------------------------------------------------------------------------------- 1 | x = [] 2 | for key k in { one: 2, three: 4, five: 6 }: x.push(k) 3 | assert.deepEqual(x, ["one", "three", "five"]) 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/obj-val-key.js: -------------------------------------------------------------------------------- 1 | x = [] 2 | for val v, key k in { one: 2, three: 4, five: 6 }: x.push([k,v]) 3 | assert.deepEqual(x, [["one", 2], ["three", 4], ["five", 6]]) 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/obj-val.js: -------------------------------------------------------------------------------- 1 | x = [] 2 | for val v in { one: 2, three: 4, five: 6 }: x.push(v) 3 | assert.deepEqual(x, [2, 4, 6]) 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/object-identifier/actual.js: -------------------------------------------------------------------------------- 1 | for key k in obj: k 2 | -------------------------------------------------------------------------------- /test/fixtures/for-in/object-identifier/expected.js: -------------------------------------------------------------------------------- 1 | for (let _i = 0, _keys = Object.keys(obj), _len = _keys.length; _i < _len; _i++) { 2 | const k = _keys[_i]; 3 | k; 4 | } -------------------------------------------------------------------------------- /test/fixtures/for-in/object-own-properties.js: -------------------------------------------------------------------------------- 1 | Constructor() -> this 2 | Constructor.prototype = { shouldntSee: 'me' } 3 | 4 | obj = new Constructor 5 | obj.shouldSee = 'this' 6 | 7 | keys = [for const k in obj: k] 8 | assert.deepEqual(keys, ['shouldSee', 'shouldntSee']) 9 | 10 | for key k in obj: 11 | assert(k == 'shouldSee') 12 | -------------------------------------------------------------------------------- /test/fixtures/for-in/plain-array/actual.js: -------------------------------------------------------------------------------- 1 | for elem e in [1, 2, 3]: e 2 | -------------------------------------------------------------------------------- /test/fixtures/for-in/plain-array/expected.js: -------------------------------------------------------------------------------- 1 | for (let _arr = [1, 2, 3], _i = 0, _len = _arr.length; _i < _len; _i++) { 2 | const e = _arr[_i]; 3 | e; 4 | } -------------------------------------------------------------------------------- /test/fixtures/for-in/plain-object/actual.js: -------------------------------------------------------------------------------- 1 | for key k, val v in {one: 1, two: 2, three: 3}: k 2 | -------------------------------------------------------------------------------- /test/fixtures/for-in/plain-object/expected.js: -------------------------------------------------------------------------------- 1 | for (let _obj = { one: 1, two: 2, three: 3 }, _i = 0, _keys = Object.keys(_obj), _len = _keys.length; _i < _len; _i++) { 2 | const k = _keys[_i]; 3 | const v = _obj[k]; 4 | k; 5 | } -------------------------------------------------------------------------------- /test/fixtures/for-in/scope-ordering/actual.js: -------------------------------------------------------------------------------- 1 | f() -> 2 | sideEffect0() 3 | for key k1 in sideEffect1(): k1 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/scope-ordering/expected.js: -------------------------------------------------------------------------------- 1 | function f() { 2 | sideEffect0(); 3 | 4 | for (let _obj = sideEffect1(), _i = 0, _keys = Object.keys(_obj), _len = _keys.length; _i < _len; _i++) { 5 | const k1 = _keys[_i]; 6 | k1; 7 | } 8 | } -------------------------------------------------------------------------------- /test/fixtures/for-in/scope-register-declaration/actual.js: -------------------------------------------------------------------------------- 1 | f() -> 2 | for key k in g(): k 3 | for key k in g(): k 4 | -------------------------------------------------------------------------------- /test/fixtures/for-in/scope-register-declaration/expected.js: -------------------------------------------------------------------------------- 1 | function f() { 2 | for (let _obj = g(), _i = 0, _keys = Object.keys(_obj), _len = _keys.length; _i < _len; _i++) { 3 | const k = _keys[_i]; 4 | k; 5 | } 6 | 7 | for (let _obj2 = g(), _i2 = 0, _keys2 = Object.keys(_obj2), _len2 = _keys2.length; _i2 < _len2; _i2++) { 8 | const k = _keys2[_i2]; 9 | k; 10 | } 11 | } -------------------------------------------------------------------------------- /test/fixtures/for-of/not-prefixed/actual.js: -------------------------------------------------------------------------------- 1 | for x of generator: x 2 | -------------------------------------------------------------------------------- /test/fixtures/for-of/not-prefixed/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "for-of requires a variable qualifier: `now` to reassign an existing variable, or `const`, `let`, `var` to declare a new one. (1:4)" 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/for-of/now/actual.js: -------------------------------------------------------------------------------- 1 | for now x of generator: x 2 | -------------------------------------------------------------------------------- /test/fixtures/for-of/now/expected.js: -------------------------------------------------------------------------------- 1 | for (x of generator) x; 2 | -------------------------------------------------------------------------------- /test/fixtures/for/i-arr-plain.js: -------------------------------------------------------------------------------- 1 | arr = [4, 5, 6] 2 | let x 3 | for idx i in arr: 4 | now x = i 5 | 6 | assert.equal(x, 2) 7 | -------------------------------------------------------------------------------- /test/fixtures/for/i-x-arr-plain.js: -------------------------------------------------------------------------------- 1 | arr = [4, 5, 6] 2 | 3 | let x, y 4 | for idx i, elem e in arr: 5 | now x = i 6 | now y = e 7 | 8 | assert.equal(x, 2) 9 | assert.equal(y, 6) 10 | -------------------------------------------------------------------------------- /test/fixtures/for/in-obj.js: -------------------------------------------------------------------------------- 1 | let y 2 | for const k in { x: 8 }: 3 | now y = k 4 | 5 | assert.equal(y, "x") 6 | -------------------------------------------------------------------------------- /test/fixtures/for/nested.js: -------------------------------------------------------------------------------- 1 | let x 2 | for let i=0; i<10; i++: 3 | for let j=0; j<10; j++: 4 | now x = i + j 5 | assert.equal(x, 18) 6 | 7 | let y 8 | for let i=0; i<10; i++: for let j=0; j<10; j++: now y = i + j 9 | assert.equal(y, 18) 10 | -------------------------------------------------------------------------------- /test/fixtures/for/of-arr.js: -------------------------------------------------------------------------------- 1 | let y 2 | for const [ x ] of [ [1], [4, 0] ]: 3 | now y = x 4 | 5 | assert.equal(y, 4) 6 | -------------------------------------------------------------------------------- /test/fixtures/for/of-obj.js: -------------------------------------------------------------------------------- 1 | let y 2 | for const { x } of [{ x: 8 }, { x: 4 }]: 3 | now y = x 4 | 5 | assert.equal(y, 4) 6 | -------------------------------------------------------------------------------- /test/fixtures/for/of-plain.js: -------------------------------------------------------------------------------- 1 | let y 2 | for const x of [4]: 3 | now y = x 4 | 5 | assert.equal(y, 4) 6 | -------------------------------------------------------------------------------- /test/fixtures/for/semi-semi-colon.js: -------------------------------------------------------------------------------- 1 | let x; 2 | for let i = 0; i < 10; i++: 3 | now x = i; 4 | 5 | assert.equal(x, 9); 6 | -------------------------------------------------------------------------------- /test/fixtures/for/semi-semi-paren-free.js: -------------------------------------------------------------------------------- 1 | let x 2 | for let i = 0; i < 10; i++ { 3 | now x = i 4 | } 5 | 6 | assert.equal(x, 9) 7 | -------------------------------------------------------------------------------- /test/fixtures/for/semi-semi-paren.js: -------------------------------------------------------------------------------- 1 | let x 2 | for (let i = 0; i < 10; i++) { 3 | now x = i 4 | } 5 | 6 | assert.equal(x, 9) 7 | -------------------------------------------------------------------------------- /test/fixtures/if-expressions/blocks/actual.js: -------------------------------------------------------------------------------- 1 | x = if true: 2 | 1 3 | 1 4 | elif true: 5 | for const x of []: 6 | x 7 | else if true: 8 | 3 9 | else: 10 | 4 11 | 4 12 | -------------------------------------------------------------------------------- /test/fixtures/if-expressions/blocks/expected.js: -------------------------------------------------------------------------------- 1 | const x = true ? (1, 1) : true ? function () { 2 | var _ret; 3 | 4 | for (const x of []) { 5 | _ret = x; 6 | }return _ret; 7 | }() : true ? 3 : (4, 4); 8 | -------------------------------------------------------------------------------- /test/fixtures/if-expressions/no-alternate/actual.js: -------------------------------------------------------------------------------- 1 | x = if true: 1 2 | -------------------------------------------------------------------------------- /test/fixtures/if-expressions/no-alternate/expected.js: -------------------------------------------------------------------------------- 1 | const x = true ? 1 : null; 2 | -------------------------------------------------------------------------------- /test/fixtures/if-expressions/oneline/actual.js: -------------------------------------------------------------------------------- 1 | x = if true: 1 elif true: 2 else if true: 3 else: 4 2 | -------------------------------------------------------------------------------- /test/fixtures/if-expressions/oneline/expected.js: -------------------------------------------------------------------------------- 1 | const x = true ? 1 : true ? 2 : true ? 3 : 4; 2 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/assign/actual.js: -------------------------------------------------------------------------------- 1 | fn(x) -> 2 | now x = 4 3 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/assign/expected.js: -------------------------------------------------------------------------------- 1 | function fn(x) { 2 | return x = 4; 3 | } -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/await-assign/actual.js: -------------------------------------------------------------------------------- 1 | fn() -/> 2 | x <- f() 3 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/await-assign/expected.js: -------------------------------------------------------------------------------- 1 | async function fn() { 2 | const x = await f(); 3 | return x; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/basic.js: -------------------------------------------------------------------------------- 1 | fn(x) -> 1 2 | assert.equal(fn(), 1) 3 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/branched.js: -------------------------------------------------------------------------------- 1 | f(x) -> 2 | if (false) { 3 | 1 4 | } else { 5 | 2 6 | 3 7 | } 8 | 9 | assert.equal(f(), 3) 10 | 11 | 12 | g() -> 13 | if false: 14 | 2 15 | else if false: 16 | 3 17 | else if true: 18 | 4 19 | else: 20 | 5 21 | 22 | assert.equal(g(), 4) 23 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/const/actual.js: -------------------------------------------------------------------------------- 1 | fn() -> 2 | x = 4 3 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/const/expected.js: -------------------------------------------------------------------------------- 1 | function fn() { 2 | const x = 4; 3 | return x; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/constructor-no-return/actual.js: -------------------------------------------------------------------------------- 1 | class X { 2 | constructor() -> 1 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/constructor-no-return/expected.js: -------------------------------------------------------------------------------- 1 | class X { 2 | constructor() { 3 | 1; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/curly.js: -------------------------------------------------------------------------------- 1 | fn(x) -> { 1 } 2 | assert.equal(fn(), 1) 3 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/inner-functions-arrow/actual.js: -------------------------------------------------------------------------------- 1 | fn() -> 2 | value = 42 3 | 4 | inner() -> 5 | value 6 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/inner-functions-arrow/expected.js: -------------------------------------------------------------------------------- 1 | function fn() { 2 | const value = 42; 3 | 4 | function inner() { 5 | return value; 6 | } 7 | 8 | return inner; 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/inner-functions/actual.js: -------------------------------------------------------------------------------- 1 | function outer() { 2 | function inner() {} 3 | } -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/inner-functions/expected.js: -------------------------------------------------------------------------------- 1 | function outer() { 2 | function inner() {} 3 | return inner; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/loop-branched-one-retval/actual.js: -------------------------------------------------------------------------------- 1 | f() -> 2 | for const x of []: 3 | if 0: 4 | 0 5 | else if 1: 6 | 1 7 | else: 8 | 2 9 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/loop-branched-one-retval/expected.js: -------------------------------------------------------------------------------- 1 | function f() { 2 | for (const x of []) { 3 | if (0) { 4 | 0; 5 | } else if (1) { 6 | 1; 7 | } else { 8 | 2; 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/loop.js: -------------------------------------------------------------------------------- 1 | fn(x) -> 2 | for let i=0; i<10; i++: 3 | i 4 | 5 | assert.equal(fn(), undefined); 6 | 7 | 8 | for let i=0; i<1; i++: 9 | fn2() -> 10 | 1 11 | assert.equal(fn2(), 1) 12 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/member-assign/actual.js: -------------------------------------------------------------------------------- 1 | fn(obj) -> 2 | obj.x = 4 3 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/member-assign/expected.js: -------------------------------------------------------------------------------- 1 | function fn(obj) { 2 | return obj.x = 4; 3 | } -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/set-no-return/actual.js: -------------------------------------------------------------------------------- 1 | class X { 2 | y(z) -set> 3 | this.z = z 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/set-no-return/expected.js: -------------------------------------------------------------------------------- 1 | class X { 2 | set y(z) { 3 | this.z = z; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/void-assign/actual.js: -------------------------------------------------------------------------------- 1 | fn(x): void -> 2 | now x = 4 3 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/void-assign/expected.js: -------------------------------------------------------------------------------- 1 | function fn(x): void { 2 | x = 4; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/void/actual.js: -------------------------------------------------------------------------------- 1 | fn1(): void -> 1 2 | 3 | fn2(): void => 1 4 | -------------------------------------------------------------------------------- /test/fixtures/implicit-returns/void/expected.js: -------------------------------------------------------------------------------- 1 | function fn1(): void { 2 | 1; 3 | } 4 | 5 | const fn2 = (): void => 1; 6 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/async/actual.js: -------------------------------------------------------------------------------- 1 | fn() -/> 2 | await 1 3 | await 2 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/async/expected.js: -------------------------------------------------------------------------------- 1 | async function fn() { 2 | await 1; 3 | return 2; 4 | } -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/basic/actual.js: -------------------------------------------------------------------------------- 1 | fn() -> 2 | 1 3 | 2 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/basic/expected.js: -------------------------------------------------------------------------------- 1 | function fn() { 2 | 1; 3 | return 2; 4 | } -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/curly/actual.js: -------------------------------------------------------------------------------- 1 | fn() -> { 2 | 1 3 | 2 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/curly/expected.js: -------------------------------------------------------------------------------- 1 | function fn() { 2 | 1; 3 | return 2; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/fat-async/actual.js: -------------------------------------------------------------------------------- 1 | fn() =/> 2 | await 1 3 | await 2 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/fat-async/expected.js: -------------------------------------------------------------------------------- 1 | const fn = async () => { 2 | await 1; 3 | return 2; 4 | }; -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/fat-basic/actual.js: -------------------------------------------------------------------------------- 1 | fn() => 2 | 1 3 | 2 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/fat-basic/expected.js: -------------------------------------------------------------------------------- 1 | const fn = () => { 2 | 1; 3 | return 2; 4 | }; 5 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/fat-generator-expression/actual.js: -------------------------------------------------------------------------------- 1 | x = fn() =*> 2 | yield 1 3 | yield 2 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/fat-generator-expression/expected.js: -------------------------------------------------------------------------------- 1 | const x = function* fn() { 2 | yield 1; 3 | return yield 2; 4 | }.bind(this); 5 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/fat-generator-statement/actual.js: -------------------------------------------------------------------------------- 1 | fn() =*> 2 | yield this 3 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/fat-generator-statement/expected.js: -------------------------------------------------------------------------------- 1 | function* fn() { 2 | return yield this; 3 | } 4 | 5 | fn = fn.bind(this); 6 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/fat-oneline/actual.js: -------------------------------------------------------------------------------- 1 | fn() => 1 2 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/fat-oneline/expected.js: -------------------------------------------------------------------------------- 1 | const fn = () => 1; 2 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/fat-twoline-unfortunate/actual.js: -------------------------------------------------------------------------------- 1 | fn() => 2 | 1 3 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/fat-twoline-unfortunate/expected.js: -------------------------------------------------------------------------------- 1 | const fn = () => { 2 | return 1; 3 | }; 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/function-expressions-fat-unfortunate/actual.js: -------------------------------------------------------------------------------- 1 | x = fn() => 1 2 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/function-expressions-fat-unfortunate/expected.js: -------------------------------------------------------------------------------- 1 | const x = () => 1; 2 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/function-expressions/actual.js: -------------------------------------------------------------------------------- 1 | x = fn() -> 1 2 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/function-expressions/expected.js: -------------------------------------------------------------------------------- 1 | const x = function fn() { 2 | return 1; 3 | }; 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/generator-curly/actual.js: -------------------------------------------------------------------------------- 1 | fn() -*> { 2 | yield 1 3 | yield 2 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/generator-curly/expected.js: -------------------------------------------------------------------------------- 1 | function* fn() { 2 | yield 1; 3 | return yield 2; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/generator-void/actual.js: -------------------------------------------------------------------------------- 1 | fn(): void -*> 2 | yield 1 3 | yield 2 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/generator-void/expected.js: -------------------------------------------------------------------------------- 1 | function* fn(): void { 2 | yield 1; 3 | yield 2; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/generator/actual.js: -------------------------------------------------------------------------------- 1 | fn() -*> 2 | yield 1 3 | yield 2 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/generator/expected.js: -------------------------------------------------------------------------------- 1 | function* fn() { 2 | yield 1; 3 | return yield 2; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/member-fat-generator/actual.js: -------------------------------------------------------------------------------- 1 | x.fn() =*> yield 1 2 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/member-fat-generator/expected.js: -------------------------------------------------------------------------------- 1 | x.fn = function* fn() { 2 | return yield 1; 3 | }.bind(x); 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/member-fat/actual.js: -------------------------------------------------------------------------------- 1 | x.fn() => 1 2 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/member-fat/expected.js: -------------------------------------------------------------------------------- 1 | x.fn = function fn() { 2 | return 1; 3 | }.bind(x); 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/member/actual.js: -------------------------------------------------------------------------------- 1 | x.fn() -> 1 2 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/member/expected.js: -------------------------------------------------------------------------------- 1 | x.fn = function fn() { 2 | return 1; 3 | }; 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/oneline/actual.js: -------------------------------------------------------------------------------- 1 | fn() -> 1 2 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/oneline/expected.js: -------------------------------------------------------------------------------- 1 | function fn() { 2 | return 1; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/void/actual.js: -------------------------------------------------------------------------------- 1 | fn(): void -> 2 | 1 3 | 2 4 | -------------------------------------------------------------------------------- /test/fixtures/named-arrow-functions/void/expected.js: -------------------------------------------------------------------------------- 1 | function fn(): void { 2 | 1; 3 | 2; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["lightscript"] 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/safe-member-expression/basic/actual.js: -------------------------------------------------------------------------------- 1 | x?.y 2 | -------------------------------------------------------------------------------- /test/fixtures/safe-member-expression/basic/exec.js: -------------------------------------------------------------------------------- 1 | const o = { x: 1 }; 2 | 3 | assert.equal(o?.x, 1); 4 | assert.equal(o?.n?.x, null); 5 | -------------------------------------------------------------------------------- /test/fixtures/safe-member-expression/basic/expected.js: -------------------------------------------------------------------------------- 1 | x == null ? null : x.y; -------------------------------------------------------------------------------- /test/fixtures/safe-member-expression/calls-after/actual.js: -------------------------------------------------------------------------------- 1 | a?.b() 2 | 3 | a?.b()?.c().d.e() 4 | 5 | a?.b().c?.d().e.f() 6 | 7 | a?.b~c() 8 | 9 | a?.b~c()?.d~e() 10 | -------------------------------------------------------------------------------- /test/fixtures/safe-member-expression/calls-after/exec.js: -------------------------------------------------------------------------------- 1 | a = { 2 | b() -> 1 3 | } 4 | assert.equal(a?.b(), 1) 5 | 6 | c = null 7 | assert.equal(c?.b(), null) 8 | 9 | // use if blocks for variable name reuse 10 | if (true) { 11 | g() -> 1 12 | f() -> 13 | { g } 14 | e() -> 15 | { f } 16 | d = { e } 17 | assert.equal(d?.e()?.f().g(), 1) 18 | } 19 | 20 | if (true) { 21 | e() -> 22 | null 23 | d = { e } 24 | assert.equal(d?.e()?.f().g(), null) 25 | } 26 | 27 | if (true) { 28 | d = null 29 | assert.equal(d?.e()?.f().g(), null) 30 | } 31 | -------------------------------------------------------------------------------- /test/fixtures/safe-member-expression/calls-after/expected.js: -------------------------------------------------------------------------------- 1 | var _ref, _ref2, _ref3; 2 | 3 | a == null ? null : a.b(); 4 | 5 | (_ref = a == null ? null : a.b()) == null ? null : _ref.c().d.e(); 6 | 7 | (_ref2 = a == null ? null : a.b().c) == null ? null : _ref2.d().e.f(); 8 | 9 | a == null ? null : c(a.b); 10 | 11 | (_ref3 = a == null ? null : c(a.b)) == null ? null : e(_ref3.d); 12 | -------------------------------------------------------------------------------- /test/fixtures/safe-member-expression/chained/actual.js: -------------------------------------------------------------------------------- 1 | x?.y?.z?.a 2 | 3 | x.y?.z 4 | 5 | f()?.y?.z 6 | 7 | x.f().z?.y?.z 8 | -------------------------------------------------------------------------------- /test/fixtures/safe-member-expression/chained/exec.js: -------------------------------------------------------------------------------- 1 | const o = { x: { y: 1 } }; 2 | 3 | assert.equal(o?.x?.y, 1); 4 | assert.equal(o.x?.y, 1); 5 | assert.equal(o?.x?.n?.y, null); 6 | -------------------------------------------------------------------------------- /test/fixtures/safe-member-expression/chained/expected.js: -------------------------------------------------------------------------------- 1 | var _ref, _ref2, _ref3; 2 | 3 | ((x == null ? null : x.y) == null ? null : x.y.z) == null ? null : x.y.z.a; 4 | 5 | (_ref = x.y) == null ? null : _ref.z; 6 | 7 | ((_ref2 = f()) == null ? null : _ref2.y) == null ? null : _ref2.y.z; 8 | 9 | ((_ref3 = x.f().z) == null ? null : _ref3.y) == null ? null : _ref3.y.z; -------------------------------------------------------------------------------- /test/fixtures/safe-member-expression/computed/actual.js: -------------------------------------------------------------------------------- 1 | x?[y]?.z?[a] 2 | -------------------------------------------------------------------------------- /test/fixtures/safe-member-expression/computed/exec.js: -------------------------------------------------------------------------------- 1 | const o = { x: { y: 1 } }; 2 | 3 | assert.equal(o?['x']?['y'], 1); 4 | assert.equal(o.x?['y'], 1); 5 | assert.equal(o?['x']?['n']?['y'], null); 6 | -------------------------------------------------------------------------------- /test/fixtures/safe-member-expression/computed/expected.js: -------------------------------------------------------------------------------- 1 | ((x == null ? null : x[y]) == null ? null : x[y].z) == null ? null : x[y].z[a]; -------------------------------------------------------------------------------- /test/fixtures/stdlib/bitwise-ops/actual.js: -------------------------------------------------------------------------------- 1 | bitwiseNot(1) 2 | bitwiseAnd(0, 1) 3 | bitwiseOr(0, 1) 4 | bitwiseXor(0, 1) 5 | bitwiseLeftShift(0, 1) 6 | bitwiseRightShift(0, 1) 7 | bitwiseZeroFillRightShift(0, 1) 8 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/bitwise-ops/exec.js: -------------------------------------------------------------------------------- 1 | assert.equal(bitwiseNot(1), -2) 2 | 3 | assert.equal(bitwiseAnd(0, 0), 0) 4 | assert.equal(bitwiseAnd(0, 1), 0) 5 | assert.equal(bitwiseAnd(1, 1), 1) 6 | assert.equal(bitwiseAnd(1, 2), 0) 7 | assert.equal(bitwiseAnd(2, 2), 2) 8 | 9 | assert.equal(bitwiseOr(0, 0), 0) 10 | assert.equal(bitwiseOr(0, 1), 1) 11 | assert.equal(bitwiseOr(1, 1), 1) 12 | assert.equal(bitwiseOr(1, 2), 3) 13 | assert.equal(bitwiseOr(2, 2), 2) 14 | 15 | assert.equal(bitwiseXor(0, 0), 0) 16 | assert.equal(bitwiseXor(0, 1), 1) 17 | assert.equal(bitwiseXor(1, 1), 0) 18 | assert.equal(bitwiseXor(1, 2), 3) 19 | assert.equal(bitwiseXor(2, 2), 0) 20 | 21 | assert.equal(bitwiseLeftShift(0, 0), 0) 22 | assert.equal(bitwiseLeftShift(0, 1), 0) 23 | assert.equal(bitwiseLeftShift(1, 1), 2) 24 | assert.equal(bitwiseLeftShift(1, 2), 4) 25 | assert.equal(bitwiseLeftShift(2, 2), 8) 26 | 27 | assert.equal(bitwiseRightShift(0, 0), 0) 28 | assert.equal(bitwiseRightShift(0, 1), 0) 29 | assert.equal(bitwiseRightShift(1, 1), 0) 30 | assert.equal(bitwiseRightShift(1, 2), 0) 31 | assert.equal(bitwiseRightShift(2, 1), 1) 32 | assert.equal(bitwiseRightShift(2, 0), 2) 33 | assert.equal(bitwiseRightShift(-1, 2), -1) 34 | 35 | assert.equal(bitwiseZeroFillRightShift(0, 0), 0) 36 | assert.equal(bitwiseZeroFillRightShift(0, 1), 0) 37 | assert.equal(bitwiseZeroFillRightShift(1, 1), 0) 38 | assert.equal(bitwiseZeroFillRightShift(1, 2), 0) 39 | assert.equal(bitwiseZeroFillRightShift(2, 1), 1) 40 | assert.equal(bitwiseZeroFillRightShift(2, 0), 2) 41 | assert.equal(bitwiseZeroFillRightShift(-1, 2), 1073741823) 42 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/bitwise-ops/expected.js: -------------------------------------------------------------------------------- 1 | function bitwiseNot(a) { 2 | return ~a; 3 | } 4 | 5 | function bitwiseAnd(a, b) { 6 | return a & b; 7 | } 8 | 9 | function bitwiseOr(a, b) { 10 | return a | b; 11 | } 12 | 13 | function bitwiseXor(a, b) { 14 | return a ^ b; 15 | } 16 | 17 | function bitwiseLeftShift(a, b) { 18 | return a << b; 19 | } 20 | 21 | function bitwiseRightShift(a, b) { 22 | return a >> b; 23 | } 24 | 25 | function bitwiseZeroFillRightShift(a, b) { 26 | return a >>> b; 27 | } 28 | 29 | bitwiseNot(1); 30 | bitwiseAnd(0, 1); 31 | bitwiseOr(0, 1); 32 | bitwiseXor(0, 1); 33 | bitwiseLeftShift(0, 1); 34 | bitwiseRightShift(0, 1); 35 | bitwiseZeroFillRightShift(0, 1); -------------------------------------------------------------------------------- /test/fixtures/stdlib/disabled/actual.js: -------------------------------------------------------------------------------- 1 | map() 2 | looseEq() 3 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/disabled/expected.js: -------------------------------------------------------------------------------- 1 | map(); 2 | looseEq(); 3 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/disabled/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | ["lightscript", { 4 | "stdlib": false 5 | }] 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/kitchen-sink/actual.js: -------------------------------------------------------------------------------- 1 | looseEq(1, '1') 2 | looseNotEq(1, '1') 3 | foo(1, '1') 4 | uniq(x) -> x 5 | map([0.1, 0.2, 0.5, 0.9], round)~uniq() 6 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/kitchen-sink/expected.js: -------------------------------------------------------------------------------- 1 | import map from 'lodash/map'; 2 | import round from 'lodash/round'; 3 | 4 | function looseEq(a, b) { 5 | return a == b; 6 | } 7 | 8 | function looseNotEq(a, b) { 9 | return a != b; 10 | } 11 | 12 | looseEq(1, '1'); 13 | looseNotEq(1, '1'); 14 | foo(1, '1'); 15 | 16 | function uniq(x) { 17 | return x; 18 | } 19 | 20 | uniq(map([0.1, 0.2, 0.5, 0.9], round)); -------------------------------------------------------------------------------- /test/fixtures/stdlib/lightscript-disabled/actual.js: -------------------------------------------------------------------------------- 1 | looseEq() 2 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/lightscript-disabled/expected.js: -------------------------------------------------------------------------------- 1 | looseEq(); 2 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/lightscript-disabled/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | ["lightscript", { 4 | "stdlib": { 5 | "lightscript": false 6 | } 7 | }] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/lightscript-stdlib-works/exec.js: -------------------------------------------------------------------------------- 1 | assert.equal(looseEq(1, '1'), true) 2 | assert.equal(looseEq(1, 1), true) 3 | assert.equal(looseEq(1, '2'), false) 4 | assert.equal(looseEq(1, 2), false) 5 | assert.equal(looseEq(1, true), true) 6 | assert.equal(looseEq(2, true), false) 7 | 8 | assert.equal(looseNotEq(1, '1'), false) 9 | assert.equal(looseNotEq(1, '2'), true) 10 | assert.equal(looseNotEq(1, 1), false) 11 | assert.equal(looseNotEq('hi', false), true) 12 | 13 | assert.equal(bitwiseNot(1), -2) 14 | assert.equal(bitwiseNot(bitwiseNot(1)), 1) 15 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/lightscript-stdlib-works/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["lightscript", "transform-es2015-modules-commonjs"] 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/lodash-disabled/actual.js: -------------------------------------------------------------------------------- 1 | uniq() 2 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/lodash-disabled/expected.js: -------------------------------------------------------------------------------- 1 | uniq(); 2 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/lodash-disabled/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | ["lightscript", { 4 | "stdlib": { 5 | "lodash": false 6 | } 7 | }] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/lodash-true/actual.js: -------------------------------------------------------------------------------- 1 | uniq() 2 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/lodash-true/expected.js: -------------------------------------------------------------------------------- 1 | import uniq from "lodash/uniq"; 2 | uniq(); -------------------------------------------------------------------------------- /test/fixtures/stdlib/lodash-true/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | ["lightscript", { 4 | "stdlib": { 5 | "lodash": true 6 | } 7 | }] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/overridden/actual.js: -------------------------------------------------------------------------------- 1 | uniq() -> 1 2 | uniq() 3 | map() 4 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/overridden/expected.js: -------------------------------------------------------------------------------- 1 | import map from "lodash/map"; 2 | 3 | function uniq() { 4 | return 1; 5 | } 6 | 7 | uniq(); 8 | map(); -------------------------------------------------------------------------------- /test/fixtures/stdlib/require-true/actual.js: -------------------------------------------------------------------------------- 1 | looseEq(1, '1') 2 | looseNotEq(1, '1') 3 | foo(1, '1') 4 | uniq(x) -> x 5 | map([0.1, 0.2, 0.5, 0.9], round)~uniq() 6 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/require-true/exec.js: -------------------------------------------------------------------------------- 1 | assert.equal(looseEq(1, '1'), true) 2 | assert.equal(looseEq(1, 1), true) 3 | assert.equal(looseEq(1, '2'), false) 4 | assert.equal(looseEq(1, 2), false) 5 | assert.equal(looseEq(1, true), true) 6 | assert.equal(looseEq(2, true), false) 7 | 8 | assert.equal(looseNotEq(1, '1'), false) 9 | assert.equal(looseNotEq(1, '2'), true) 10 | assert.equal(looseNotEq(1, 1), false) 11 | assert.equal(looseNotEq('hi', false), true) 12 | 13 | assert.equal(bitwiseNot(1), -2) 14 | assert.equal(bitwiseNot(bitwiseNot(1)), 1) 15 | -------------------------------------------------------------------------------- /test/fixtures/stdlib/require-true/expected.js: -------------------------------------------------------------------------------- 1 | function looseEq(a, b) { 2 | return a == b; 3 | } 4 | 5 | function looseNotEq(a, b) { 6 | return a != b; 7 | } 8 | 9 | const map = require('lodash/map'); 10 | 11 | const round = require('lodash/round'); 12 | 13 | looseEq(1, '1'); 14 | looseNotEq(1, '1'); 15 | foo(1, '1'); 16 | 17 | function uniq(x) { 18 | return x; 19 | } 20 | 21 | uniq(map([0.1, 0.2, 0.5, 0.9], round)); -------------------------------------------------------------------------------- /test/fixtures/stdlib/require-true/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | ["lightscript", { 4 | "stdlib": { 5 | "require": true 6 | } 7 | }] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/tilde-calls/basic.js: -------------------------------------------------------------------------------- 1 | f(...args) -> args 2 | o = { 3 | a: 2 4 | m() => this 5 | g(x) -> x + 1 6 | } 7 | 8 | assert.deepEqual(1~f(), [1]) 9 | assert.deepEqual(1~f(3), [1, 3]) 10 | assert.deepEqual(1~f(3, 5, 6), [1, 3, 5, 6]) 11 | assert.equal(5~Math.pow(3), 125) 12 | -------------------------------------------------------------------------------- /test/fixtures/tilde-calls/subscripts.js: -------------------------------------------------------------------------------- 1 | f(...args) -> args 2 | o = { 3 | a: 2 4 | m() => this 5 | g(x) -> x + 1 6 | } 7 | 8 | assert.equal(1~o.g(), 2) 9 | assert.equal(1~o["g"](), 2) 10 | assert.deepEqual( 11 | o.m().a 12 | ~o.g() 13 | .toString() 14 | ~f() 15 | , ["3"]) 16 | -------------------------------------------------------------------------------- /test/fixtures/variables/for-in-elem/actual.js: -------------------------------------------------------------------------------- 1 | for idx i, elem x in [4, 5, 6]: 2 | x = 1 3 | -------------------------------------------------------------------------------- /test/fixtures/variables/for-in-elem/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "Duplicate declaration \"x\"" 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/variables/for-in-idx/actual.js: -------------------------------------------------------------------------------- 1 | for idx i, elem x in [4, 5, 6]: 2 | i = 1 3 | -------------------------------------------------------------------------------- /test/fixtures/variables/for-in-idx/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "`i` is shadowed" 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/variables/for-in-key/actual.js: -------------------------------------------------------------------------------- 1 | for key k, val v in {one: 2}: 2 | k = 1 3 | -------------------------------------------------------------------------------- /test/fixtures/variables/for-in-key/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "Duplicate declaration \"k\"" 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/variables/for-in-val/actual.js: -------------------------------------------------------------------------------- 1 | for key k, val v in {one: 2}: 2 | v = 1 3 | -------------------------------------------------------------------------------- /test/fixtures/variables/for-in-val/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "Duplicate declaration \"v\"" 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/variables/function/actual.js: -------------------------------------------------------------------------------- 1 | fn() -> 1 2 | 3 | fn = 3 4 | -------------------------------------------------------------------------------- /test/fixtures/variables/function/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "Duplicate declaration \"fn\"" 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/variables/no-now-update-assignment/actual.js: -------------------------------------------------------------------------------- 1 | x += 2 2 | -------------------------------------------------------------------------------- /test/fixtures/variables/no-now-update-assignment/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "Incorrect assignment: to reassign, use `now`; to assign as `const`, put on its own line." 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/variables/now-member/actual.js: -------------------------------------------------------------------------------- 1 | x = {} 2 | a = {} 3 | 4 | x.y = z 5 | now a.b = c 6 | -------------------------------------------------------------------------------- /test/fixtures/variables/now-member/expected.js: -------------------------------------------------------------------------------- 1 | const x = {}; 2 | const a = {}; 3 | 4 | x.y = z; 5 | a.b = c; 6 | -------------------------------------------------------------------------------- /test/fixtures/variables/now-missing/actual.js: -------------------------------------------------------------------------------- 1 | if x = 7: foo 2 | -------------------------------------------------------------------------------- /test/fixtures/variables/now-missing/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "Incorrect assignment: to reassign, use `now`; to assign as `const`, put on its own line." 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/variables/now-update-assignment/actual.js: -------------------------------------------------------------------------------- 1 | now x += 2 2 | -------------------------------------------------------------------------------- /test/fixtures/variables/now-update-assignment/expected.js: -------------------------------------------------------------------------------- 1 | x += 2; 2 | -------------------------------------------------------------------------------- /test/fixtures/variables/now-update-expression/actual.js: -------------------------------------------------------------------------------- 1 | x++ 2 | now y++ 3 | -------------------------------------------------------------------------------- /test/fixtures/variables/now-update-expression/expected.js: -------------------------------------------------------------------------------- 1 | x++; 2 | y++; 3 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-basic/actual.js: -------------------------------------------------------------------------------- 1 | let x 2 | if (true) { 3 | x = 1 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-basic/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "`x` is shadowed from a higher scope. If you want to reassign the variable, use `now x = ...`. If you want to declare a new shadowed `const` variable, you must use `const x = ...` explicitly." 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-destructured/actual.js: -------------------------------------------------------------------------------- 1 | let y 2 | if (true) { 3 | {x, y} = {} 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-destructured/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "`y` is shadowed from a higher scope. If you want to reassign the variable, use `now y = ...`. If you want to declare a new shadowed `const` variable, you must use `const y = ...` explicitly." 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-explicit/actual.js: -------------------------------------------------------------------------------- 1 | let x 2 | if (true) { 3 | const x = 1 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-explicit/expected.js: -------------------------------------------------------------------------------- 1 | let x; 2 | if (true) { 3 | const x = 1; 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-method-sibling/actual.js: -------------------------------------------------------------------------------- 1 | class X: 2 | m1() -> 3 | x = 1 4 | return 5 | m2() -> 6 | x = 2 7 | return 8 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-method-sibling/expected.js: -------------------------------------------------------------------------------- 1 | class X { 2 | m1() { 3 | const x = 1; 4 | return; 5 | }m2() { 6 | const x = 2; 7 | return; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-nested/actual.js: -------------------------------------------------------------------------------- 1 | if (true) { 2 | function x () {} 3 | } 4 | 5 | if (true) { 6 | x = 1 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-nested/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "`x` is shadowed from a higher scope. If you want to reassign the variable, use `now x = ...`. If you want to declare a new shadowed `const` variable, you must use `const x = ...` explicitly." 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-same-level-dup/actual.js: -------------------------------------------------------------------------------- 1 | if (true) { 2 | let x 3 | x = 1 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-same-level-dup/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "Duplicate declaration \"x\"" 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-sibling-function/actual.js: -------------------------------------------------------------------------------- 1 | f = (x) -> x 2 | 3 | g(x) -> x 4 | 5 | h() -> 6 | x = 3 7 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-sibling-function/expected.js: -------------------------------------------------------------------------------- 1 | const f = function (x) { 2 | return x; 3 | }; 4 | 5 | function g(x) { 6 | return x; 7 | } 8 | 9 | function h() { 10 | const x = 3; 11 | return x; 12 | } 13 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-sibling/actual.js: -------------------------------------------------------------------------------- 1 | if (true) { 2 | let x 3 | } 4 | 5 | if (true) { 6 | x = 1 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-sibling/expected.js: -------------------------------------------------------------------------------- 1 | if (true) { 2 | let x; 3 | } 4 | 5 | if (true) { 6 | const x = 1; 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-toplevel-dup/actual.js: -------------------------------------------------------------------------------- 1 | let x 2 | x = 1 3 | -------------------------------------------------------------------------------- /test/fixtures/variables/shadow-toplevel-dup/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "throws": "Duplicate declaration \"x\"" 3 | } 4 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | require("babel-helper-plugin-test-runner")(__dirname); 2 | --------------------------------------------------------------------------------