Giter Club home page Giter Club logo

resugar's Introduction

resugar

Rewrite your JavaScript & TypeScript source code with sweet new features.

TODO: Below is the README for esnext, the project this one came from. It will be replaced in time.


Installation

$ yarn global add esnext
# or, with `npm`:
$ npm install -g esnext

Usage

After installing, run esnext -h for comprehensive usage instructions.

Features

Functions

Translate some regular functions to arrow functions:

list.map(function(item) {
  return item.name;
});

// ↑ becomes ↓

list.map(item => item.name);

Declarations

Convert var declarations to let or const as appropriate:

var arr = [];
for (var i = 0; i < 5; i++) {
  arr.push(i);
}

// ↑ becomes ↓

const arr = [];
for (let i = 0; i < 5; i++) {
  arr.push(i);
}

Objects

Use shorthand syntax for various object constructs:

let person = {
  first: first,
  last: last,

  fullName: function() {
    return `${first} ${last}`;
  }
};

// ↑ becomes ↓

let person = {
  first,
  last,

  fullName() {
    return `${first} ${last}`;
  }
};

Strings

Convert string concatenation to string or template literals:

let name = 'Brian' + ' ' + 'Donovan';
let greeting = 'Hello, ' + name;

// ↑ becomes ↓

let name = 'Brian Donovan';
let greeting = `Hello, ${name}`;

Destructuring

Convert assignments and declarations to use object destructuring syntax:

let a = obj.a,
  b = obj.b;
(a = obj2.a), (b = obj2.b);

// ↑ becomes ↓

let { a, b } = obj;
({ a, b } = obj2);

Modules

Translate CommonJS modules into ES6 modules:

var readFile = require('fs').readFile;
const MagicString = require('magic-string');
let { ok, strictEqual: eq } = require('assert');

exports.doSomething = function() {
  ok(1);
};

// ↑ becomes ↓

import { readFile } from 'fs';
import MagicString from 'magic-string';
import { ok, strictEqual as eq } from 'assert';

export function doSomething() {
  ok(1);
}

Options

{
  'declarations.block-scope': {
    /**
     * Set this to `true` to only turn `var` into `let`, never `const`.
     */
    disableConst: boolean
  }
}

resugar's People

Contributors

adambabik avatar alangpierce avatar christophehurpeau avatar conradz avatar dependabot-preview[bot] avatar dependabot[bot] avatar eventualbuddha avatar fnd avatar github-actions[bot] avatar gitter-badger avatar globegitter avatar mathiasbynens avatar raytiley avatar rosshadden avatar steckel avatar xtian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

resugar's Issues

Error caused when destructuring within async-await re: regenerator

async function init(config) {
    var { SomeExport } = await System.import("some-module");

    return new SomeModulet(config);
}

I get some error kind of like {type: ObjectPattern, properties: [object Object], range: 57,69, loc: [object Object]} does not match type Expression

ES5 getter and setter syntax

It seems that esnext doesn't understand es5 setters and getters. Example:

var myObject = {
  get name() {return 'blah'},
  set name (value) {this.$name = value}
}

Gets mangled into:

var myObject = {
  get name() function() {return 'blah'},
  set name (value) function(value) {this.$name = value}
}

Error caused when destructuring within methods

link to examples

// All the code lines commented out would cause an error

var {x} = {x:1};

function foo({x}) {}

// NOTE: This ends up double paren-wrapped?
(function({x}){});

class bar {
    // constructor() { var {x} = {x:1}; }
    // method({x}){}
    // static func({x}) {}
    // set prop({x}){}
}

var baz = {
    // method_a: function({x}){},
    // method_b({x}){},
    // method_c(){ var {x} = {x:1}; }
    // set prop({x}){}
};

latest esnext seems to explode when encountering ImportDefaultSpecifier

import Ember from 'ember';

seems to result in:

# Pastebin bRrJiFLa
assert.js:98
  throw new assert.AssertionError({
        ^
AssertionError: did not recognize object of type "ImportDefaultSpecifier"
    at Object.getFieldNames (/Users/stefan/.nave/installed/0.11.14/lib/node_modules/esnext/node_modules/ast-types/lib/types.js:581:12)
    at LocationFixer.LFp.fix (/Users/stefan/.nave/installed/0.11.14/lib/node_modules/esnext/node_modules/recast/lib/parser.js:85:23)
    at Array.forEach (native)

example: https://github.com/stefanpenner/explosions

nested output directory

when i compile multiple files, the output directory is nested one level more deeply than the source directory:

$ esnext -o out src/**.js
src
  1.js
  2.js
out
  src
    1.js
    2.js

i would like the source and output directories to have the same level of nesting

Remove IIFE in modules.commonjs plugin

If the entire program is a single IIFE statement whose callee is a function expression with no id and a call with no arguments, we can simply strip it since the closure created by it is redundant in a module setting anyway.

(function() {
  // stuff
})();

becomes:

// stuff

Update to regenerator 0.7.9 (when released)

regenerator prior to 0.7.9 requires esprima harmony to be installed from a git:// URL. Unfortunately, many firewalls prevent installing via the git protocol. [email protected] will use [email protected] which has swapped to using esprima-fb from NPM (instead of git).

I'd like to see what changes are needed to support 0.7.x of regenerator...


Background: ember-cli includes esnext by default. We have a number of corporate and/or Windows users that cannot install due to this issue.

rest + default params

rest params are not compiled correctly when mixed with default params:

function foo(a=0, ...b) {
} 

->

function foo() {
  var b = [].slice.call(arguments, 0); // <-- should be 1, not 0
  var a = (arguments[0] !== void 0 ? arguments[0] : 0);
}

edit: i'm not sure how the spec resolves this, but for reference, this is what coffeescript does:

foo = (a=0, b...) ->

->

var foo,
  __slice = [].slice;

foo = function() {
  var a, b;
  a = arguments[0], b = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  if (a == null) {
    a = 0;
  }
};

Separation from babel?

I see that this project has been rebooted. Could you provide some context for those not familiar?

New syntax: let and const

Hello.

I'm found module that can transform AST to support let and const syntax.
But that module have one problem: they are expect filled position index in all AST nodes.
So, that module should be used before any other AST transforms.

Handle comments better when replacing source between nodes

Comments are mostly ignored right now, with the exception of arrow function transforms (see e483af4). These are just a few examples, showing the arrow function transform doing the correct thing but the others discard the comments.

"hello, " + /* world */ name;
add = function(a/*: number */, b/*: number */)/*: number */ { return a + b; };
({ a: /* A */a });

// ↑ becomes ↓

`hello, ${name}`;
add = (a/*: number */, b/*: number */)/*: number */ => a + b;
({ a });

Most likely this will involve changes similar to the change made for arrow functions where we look into the tokens associated with a node to figure out what comments may be there that we need to preserve, in addition to more careful rewriting. For the above code I propose this is the right output:

`hello, ${/* world */ name}`;
add = (a/*: number */, b/*: number */)/*: number */ => a + b;
({ /* A */a });

Object literal shorthand troubles

I have a function that looks like the following:

this.setNode = ( id, parentId, isNested ) => {
  nodeHistory = { id, parentId, isNested }
  console.log( this, nodeHistory )
}

The compiled ES5 output I'm getting is:

this.setNode = ( id, parentId, isNested ) => {
  nodeHistory = { id, parentId, isNested }
  console.log( this, nodeHistory )
}.bind(this)

As you can see, the compiler didn't seem to create the object I was expecting:

nodeHistory = { id: id, parentId: parentId, isNested: isNested }

Am I missing something? Seems simple enough. Thanks.

Destructuring with async variable throws errors

var obj = {async: true}; var {async} = obj;

/usr/lib/node_modules/esnext/node_modules/esprima-fb/esprima.js:6628
throw e;
^
Error: Line 2: Unexpected token =
at throwError (/usr/lib/node_modules/esnext/node_modules/esprima-fb/esprima.js:2371:21)
at throwUnexpected (/usr/lib/node_modules/esnext/node_modules/esprima-fb/esprima.js:2433:9)
at expect (/usr/lib/node_modules/esnext/node_modules/esprima-fb/esprima.js:2442:13)
at parseParams (/usr/lib/node_modules/esnext/node_modules/esprima-fb/esprima.js:4902:9)
at parsePropertyMethodFunction (/usr/lib/node_modules/esnext/node_modules/esprima-fb/esprima.js:2677:15)
at parseObjectProperty (/usr/lib/node_modules/esnext/node_modules/esprima-fb/esprima.js:2832:25)
at parseObjectInitialiser (/usr/lib/node_modules/esnext/node_modules/esprima-fb/esprima.js:2897:28)
at parseVariableDeclaration (/usr/lib/node_modules/esnext/node_modules/esprima-fb/esprima.js:3935:18)
at parseVariableDeclarationList (/usr/lib/node_modules/esnext/node_modules/esprima-fb/esprima.js:3966:23)
at parseVariableStatement (/usr/lib/node_modules/esnext/node_modules/esprima-fb/esprima.js:3981:24)

compile source directory

i would like to specify a source directory for esnext to compile, instead of using globs or find. this way i would not have to worry about cross platform issues in my build step

Use arrow functions when `self = this` is declared in parent scope

For example:

var self = this;
return function() {
  return self;
}

can become:

return () => this;

The usual caveats apply:

  • referencing this inside the function disqualifies it (unless it's also a .bind(this) function?)
  • referencing arguments inside the function disqualifies it (unless we can rewrite using rest params)

perf is poor.

ember-cli/ember-cli#2597 (comment)

Startup with esnext

Build successful - 73386ms.

Slowest Trees                  | Total
-------------------------------+----------------
EsnextFilter                   | 33580ms
EsnextFilter                   | 11862ms
ES3SafeFilter                | 8355ms
ES6Concatenator          | 7184ms
JSHint - App                  | 7058ms

Incremental Rebuild

Build successful - 3205ms.

Slowest Trees                  | Total
-------------------------------+----------------
ES6Concatenator          | 518ms
JSHint - App                  | 380ms
EsnextFilter                   | 357ms
ES3SafeFilter                | 351ms
Funnel                           | 349ms
TemplateCompiler         | 221ms

Startup without esnext

Build successful - 26832ms.

Slowest Trees                  | Total
-------------------------------+----------------
ES3SafeFilter                 | 9011ms
ES6Concatenator           | 6255ms
JSHint - App                   | 6211ms
JSHint - Tests                 | 2468ms

Incremental Rebuild without esnext

Build successful - 2464ms.

Slowest Trees                  | Total
-------------------------------+----------------
ES6Concatenator           | 416ms
JSHint - App                   | 361ms
ES3SafeFilter                 | 338ms
Funnel                            | 251ms
TemplateCompiler          | 221ms
Funnel                            | 148ms
Concat                            | 130ms

Generate source maps for full transforms

Recast supports input source maps, so you could do something like:

var classOutput = require('es6-class').compile(src, {
  sourceFileName: 'source.js',
  sourceMapName: 'source.js.map'
});

var arrowOutput = require('es6-arrow-function').compile(classOutput.code, {
  sourceFileName: 'source.js',
  sourceMapName: 'source.js.map',
  inputSourceMap: out.map
});

This would require a minor tweak to es6-class and es6-arrow-function to take an inputSourceMap option (might as well let users pass in any rest of Recast's options while we're at it)

Issue using esnext with es6-module-transpiler

I have been using esnext with es6-module-transpiler for a while but with the latest changes made to transpiler I now have to switch the order and run the ast produced by transpiler through esnext rather than passing an esnext transformed ast into transpiler.

The only reason this has any impact is that if using AMD/YUI/System formatters you end up with some boilerplate OUTSIDE of the module body, example:
Before:

System.register("mod", [], function(__es6_export__) {
    return {
        "setters": [],
        "execute": function() {
            "use strict";
            var $__Object$defineProperty = Object.defineProperty;
            var $__Object$create = Object.create;
            var $__Object$getPrototypeOf = Object.getPrototypeOf;
            ...
       }
    }
});

After:

var $__Object$defineProperty = Object.defineProperty;
var $__Object$create = Object.create;
var $__Object$getPrototypeOf = Object.getPrototypeOf;

System.register("mod", [], function(__es6_export__) {
    return {
        "setters": [],
        "execute": function() {
            "use strict";
            ...
       }
    }
});

The reasons for this seem linked to esnext depending on a now much older version of recast and/or ast-types. The ones used here do not seem to understand ImportNamespaceSpecifier AST node type.

Support inline source map

As far as i can tell, no options are accepted when using esnext as a browserify transform and so source maps cannot be generated?

Default arguments in fat arrow functions

I'm not entirely sure if the ES6 spec allows default parameters in arrow functions, but I would assume they do. The code below is valid in traceur but invalid with esnext.

function normalfunc(variable = "default") {
 console.log(variable); 
}

var fatarrowfunc = (variable = "default") => {
  console.log(variable);
}

only include runtime if generators is not false

Right now, it's possible to include the runtime even if generator is set to false.

Should we consider making includeRuntime part of the generator option? That way, the runtime will only be included if compiling generators is desired.

// Sample options:
{
  generator: false //no generator compilation, no runtime
}
//-------------
{
  generator: {
    includeRuntime: true //compile generators and include runtime
  }
}

not every `es6-` module needs its own copy of every module

since you do ariya/esprima.git#harmony in every es6- module, every module has its own copy of esprima. please either remove the dependencies and expect users to install it on their own or use *, which I don't know will work.

the same goes for recast, etc.

Browserify Transform and Webpack Loader

It's nice to have a cli-tool, but for use in production it's really important to be able to add esnext support to browserify and webpack.

This may not be completely simple to do because

  1. Ideally we would need to transform every file that is required in the dependency graph, but not include any runtimes
  2. If instead we were to try and compile the bundled output, it would be harder for esprima, and the bundle may not even work due to supposed 'errors'.

Issue with Browserify transform

I'm having issues using esnext as a Browserify (v8.1.0) transform.

I'm getting the following error:

assert.js:93
  throw new assert.AssertionError({
        ^
AssertionError: false == true
    at Visitor.PVp.visitWithoutReset (/Users/anthonator/Documents/Projects/clients/captivated-customer/prototype/node_modules/esnext/node_modules/recast/node_modules/ast-types/lib/path-visitor.js:135:12)
    at Visitor.PVp.visit (/Users/anthonator/Documents/Projects/clients/captivated-customer/prototype/node_modules/esnext/node_modules/recast/node_modules/ast-types/lib/path-visitor.js:117:21)
    at Function.transform (/Users/anthonator/Documents/Projects/clients/captivated-customer/prototype/node_modules/esnext/node_modules/regenerator/lib/visit.js:31:18)
    at transform (/Users/anthonator/Documents/Projects/clients/captivated-customer/prototype/node_modules/esnext/lib/index.js:87:23)
    at Function.compile (/Users/anthonator/Documents/Projects/clients/captivated-customer/prototype/node_modules/esnext/lib/index.js:34:9)
    at Stream.end (/Users/anthonator/Documents/Projects/clients/captivated-customer/prototype/node_modules/esnext/lib/index.js:160:31)
    at _end (/Users/anthonator/Documents/Projects/clients/captivated-customer/prototype/node_modules/esnext/node_modules/through/index.js:65:9)
    at Stream.stream.end (/Users/anthonator/Documents/Projects/clients/captivated-customer/prototype/node_modules/esnext/node_modules/through/index.js:74:5)
    at Transform.onend (/Users/anthonator/Documents/Projects/clients/captivated-customer/prototype/node_modules/browserify/node_modules/readable-stream/lib/_stream_readable.js:523:10)
    at Transform.g (events.js:180:16)

I've tried using the transform in my package.json and a gulp task. Both produce the same error.

'use strict';

var browserify = require('browserify'),
    esnext     = require('esnext'),
    gulp       = require('gulp'),
    rename     = require('gulp-rename'),
    source     = require('vinyl-source-stream');

gulp.task('browserify', function() {
  return (
    browserify('./js/app.js', { debug: process.env.NODE_ENV !== 'production' })
      .transform(esnext)
      .bundle()
      .pipe(source('app.js'))
      .pipe(rename('bundle.js'))
      .pipe(gulp.dest('./js'))
  );
});

I figure I'm either doing something wrong or there might be a breaking change in Browserify 8.1.0.

Destructuring doesn't play well with regenerator

That's because es6-destructuring introduces local variables after the generator was transpiled.

Consider

function* foo(bar) {
  var foo = 0;
  var i = 0;
  while (i < 5) {
    i++;
    yield foo;
    if (i % 2 === 0) {
      [foo] = bar;
    }
  }
}

for (var x of foo([1])) {
  console.log(x);
}

Output:

0
undefined
1
undefined
1

Produced code:

var foo = regeneratorRuntime.mark(function foo(bar) {
  var foo, i;

  return regeneratorRuntime.wrap(function foo$(context$1$0) {
    while (1) switch (context$1$0.prev = context$1$0.next) {
    case 0:
      foo = 0;
      i = 0;
    case 2:
      if (!(i < 5)) {
        context$1$0.next = 9;
        break;
      }

      i++;
      context$1$0.next = 6;
      return foo;
    case 6:
      if (i % 2 === 0) {
        var iterator$0 = $__getIterator(bar),
            iteratorValue$0 = {
              index: 0
            },
            foo = (iteratorValue$0 = $__getIteratorRange(iterator$0, iteratorValue$0.index, 0, 1), iteratorValue$0.range[0]);;
      }
      context$1$0.next = 2;
      break;
    case 9:
    case "end":
      return context$1$0.stop();
    }
  }, foo, this);
});

for (var x, t$0$0 = regeneratorRuntime.values(foo([1])), t$0$1; !(t$0$1 = t$0$0.next()).done; ) {
  x = t$0$1.value;
  console.log(x);
}

foo is introduced as local variable into the function generated by regenerator, shadowing the hoisted variable:

var iterator$0 = $__getIterator(bar),
      iteratorValue$0 = {
          index: 0
      },
      foo = (iteratorValue$0 = $__getIteratorRange(iterator$0, iteratorValue$0.index, 0, 1), iteratorValue$0.range[0]);

I see two possible solutions:

  • Don't declare the variables with var if it's not a variable declaration (i.e. [foo] instead of var [foo]).
  • Run regenerator after destructuring.

Remove comprehensions

Comprehensions won’t be part of ECMAScript 6. If they are in ES7, they will probably be redesigned. Thus, it is probably best to remove them from ESNext (for now).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.