diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000000..002b4aa0d5 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["env"] +} diff --git a/Cakefile b/Cakefile index f7145f2188..e8629054e8 100644 --- a/Cakefile +++ b/Cakefile @@ -70,16 +70,9 @@ transpile = (code) -> babel = require 'babel-core' presets = [] # Exclude the `modules` plugin in order to not break the `}(this));` - # at the end of the above code block. + # at the end of the `build:browser` code block. presets.push ['env', {modules: no}] unless process.env.TRANSFORM is 'false' - babelOptions = - presets: presets - sourceType: 'script' - { code } = babel.transform code, babelOptions unless presets.length is 0 - # Running Babel twice due to https://github.com/babel/babili/issues/614. - # Once that issue is fixed, move the `babili` preset back up into the - # `presets` array and run Babel once with both presets together. - presets = if process.env.MINIFY is 'false' then [] else ['babili'] + presets.push 'minify' unless process.env.MINIFY is 'false' babelOptions = compact: process.env.MINIFY isnt 'false' presets: presets @@ -100,7 +93,7 @@ testBuiltCode = (watch = no) -> buildAndTest = (includingParser = yes, harmony = no) -> process.stdout.write '\x1Bc' # Clear terminal screen. - execSync 'git checkout lib/*', stdio: [0,1,2] # Reset the generated compiler. + execSync 'git checkout lib/*', stdio: 'inherit' # Reset the generated compiler. buildArgs = ['bin/cake'] buildArgs.push if includingParser then 'build' else 'build:except-parser' @@ -494,20 +487,28 @@ task 'test:integrations', 'test the module integrated with other libraries and e # Node modules are required as part of the compiler (as opposed to the tests) # and that therefore the compiler will run in a browser environment. tmpdir = os.tmpdir() - try - buildLog = execSync "./node_modules/webpack/bin/webpack.js - --entry=./ - --output-library=CoffeeScript - --output-library-target=commonjs2 - --output-path=#{tmpdir} - --output-filename=coffeescript.js" - catch exception - console.error buildLog.toString() - throw exception - - builtCompiler = path.join tmpdir, 'coffeescript.js' - CoffeeScript = require builtCompiler - global.testingBrowser = yes - testResults = runTests CoffeeScript - fs.unlinkSync builtCompiler - process.exit 1 unless testResults + webpack = require 'webpack' + webpack { + entry: './' + output: + path: tmpdir + filename: 'coffeescript.js' + library: 'CoffeeScript' + libraryTarget: 'commonjs2' + }, (err, stats) -> + if err or stats.hasErrors() + if err + console.error err.stack or err + console.error err.details if err.details + if stats.hasErrors() + console.error error for error in stats.compilation.errors + if stats.hasWarnings() + console.warn warning for warning in stats.compilation.warnings + process.exit 1 + + builtCompiler = path.join tmpdir, 'coffeescript.js' + CoffeeScript = require builtCompiler + global.testingBrowser = yes + testResults = runTests CoffeeScript + fs.unlinkSync builtCompiler + process.exit 1 unless testResults diff --git a/docs/v2/index.html b/docs/v2/index.html index c4ed852cc4..3df4ca49de 100644 --- a/docs/v2/index.html +++ b/docs/v2/index.html @@ -527,12 +527,13 @@ Try CoffeeScript Overview CoffeeScript 2 + Compatibility Installation Usage Command Line - ES2015+ Output Node.js + Transpilation Language Reference @@ -802,13 +803,17 @@ Overview CoffeeScript 2 What’s New In CoffeeScript 2? -The biggest change in CoffeeScript 2 is that now the CoffeeScript compiler produces modern, ES2015+ JavaScript. A CoffeeScript => becomes an ES =>, a CoffeeScript class becomes an ES class and so on. With the exception of modules (import and export statements) and JSX, all the ES2015+ features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScript’s output without any further processing required. You can run the tests in your browser to see if your browser can do the same; Chrome has supported all features since version 55. -Support for ES2015+ syntax is important to ensure compatibility with frameworks that assume ES2015. Now that CoffeeScript compiles classes to the ES class keyword, it’s possible to extend an ES class; that wasn’t possible in CoffeeScript 1. Parity in how language features work is also important on its own; CoffeeScript “is just JavaScript,” and so things like function parameter default values should behave the same in CoffeeScript as in JavaScript. -Many ES2015+ features have been backported to CoffeeScript 1.11 and 1.12, including modules, for…of, and tagged template literals. Major new features unique to CoffeeScript 2 are support for ES2017’s async functions and for JSX. More details are in the changelog. +The biggest change in CoffeeScript 2 is that now the CoffeeScript compiler produces modern JavaScript syntax (ES6, or ES2015 and later). A CoffeeScript => becomes a JS =>, a CoffeeScript class becomes a JS class and so on. Major new features in CoffeeScript 2 include async functions and JSX. You can read more in the changelog. There are very few breaking changes from CoffeeScript 1.x to 2; we hope the upgrade process is smooth for most projects. -Why CoffeeScript When There’s ES2015? +Why CoffeeScript When There’s ES6? CoffeeScript introduced many new features to the JavaScript world, such as => and destructuring and classes. We are happy that ECMA has seen their utility and adopted them into ECMAScript. -CoffeeScript’s intent, however, was never to be a superset of JavaScript. One of the guiding principles of CoffeeScript has been simplicity: not just removing JavaScript’s “bad parts,” but providing an elegant, concise syntax that eschews unnecessary punctuation whenever possible, to make code easier to read and reason about. This benefit of CoffeeScript remains, even in an ES2015 world. +CoffeeScript’s intent, however, was never to be a superset of JavaScript. One of the guiding principles of CoffeeScript has been simplicity: not just removing JavaScript’s “bad parts,” but providing an elegant, concise syntax that eschews unnecessary punctuation whenever possible, to make code easier to read and reason about. This benefit of CoffeeScript remains, even in an ES2015+ world. + + + + Compatibility +With the exception of modules (import and export statements) and JSX, all the modern JavaScript features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScript’s output without any further processing required. You can run the tests in your browser to see if your browser can do the same. For older browsers or older versions of Node, transpilation is required. +Support for modern JavaScript syntax is important to ensure compatibility with frameworks that assume modern features. Now that CoffeeScript compiles classes to the class keyword, it’s possible to extend a JavaScript class; that wasn’t possible in CoffeeScript 1. Parity in how language features work is also important on its own; CoffeeScript “is just JavaScript,” and so things like function parameter default values should behave the same in CoffeeScript as in JavaScript. Some such features behave slightly differently in JavaScript than they did in CoffeeScript 1; in such cases we are conforming with the JavaScript spec, and we’ve documented the differences as breaking changes. @@ -843,6 +848,10 @@ Command Line Compile a .coffee script into a .js JavaScript file of the same name. +-t, --transpile +Pipe the CoffeeScript compiler’s output through Babel before saving or running the generated JavaScript. Requires babel-core to be installed, and options to pass to Babel in a .babelrc file or a package.json with a babel key in the path of the file or folder to be compiled. See Transpilation. + + -m, --map Generate source maps alongside the compiled JavaScript files. Adds sourceMappingURL directives to the JavaScript as well. @@ -887,20 +896,20 @@ Command Line Compile the JavaScript without the top-level function safety wrapper. --t, --tokens -Instead of parsing the CoffeeScript, just lex it, and print out the token stream. Used for debugging the compiler. - - --n, --nodes -Instead of compiling the CoffeeScript, just lex and parse it, and print out the parse tree. Used for debugging the compiler. +--no-header +Suppress the “Generated by CoffeeScript” header. --nodejs The node executable has some useful options you can set, such as --debug, --debug-brk, --max-stack-size, and --expose-gc. Use this flag to forward options directly to Node.js. To pass multiple flags, use --nodejs multiple times. ---no-header -Suppress the “Generated by CoffeeScript” header. +--tokens +Instead of parsing the CoffeeScript, just lex it, and print out the token stream. Used for debugging the compiler. + + +-n, --nodes +Instead of compiling the CoffeeScript, just lex and parse it, and print out the parse tree. Used for debugging the compiler. @@ -919,18 +928,7 @@ Examples: Start the CoffeeScript REPL (Ctrl-D to exit, Ctrl-Vfor multi-line): coffee - - - - ES2015+ Output -CoffeeScript 2 outputs the latest ES2015+ syntax. If you’re looking for a single tool that takes CoffeeScript input and generates JavaScript output that runs in any JavaScript runtime, assuming you opt out of certain newer features, stick to CoffeeScript 1.x. CoffeeScript 2 breaks compatibility with certain CoffeeScript 1.x features in order to conform with the ES2015+ specifications, and generate more idiomatic output (a CoffeeScript => becomes an ES =>; a CoffeeScript class becomes an ES class; and so on). -Since the CoffeeScript 2 compiler outputs ES2015+ syntax, it is your responsibility to either ensure that your target JavaScript runtime(s) support all these features, or that you pass the output through another transpiler like Babel, Rollup or Traceur Compiler. In general, CoffeeScript 2’s output is supported as is by Node.js 7.6+, except for modules and JSX which require transpilation. -There are many great task runners for setting up JavaScript build chains, such as Gulp, Webpack, Grunt and Broccoli. If you’re looking for a very minimal solution to get started, you can use babel-preset-env and the command line: -npm install --global coffeescript@next -npm install --save-dev coffeescript@next babel-cli babel-preset-env -coffee --print *.coffee | babel --presets env > app.js - -Note that babel-preset-env doesn’t automatically supply polyfills for your code. CoffeeScript itself will output Array.indexOf if you use the in operator, or destructuring or spread/rest syntax; and Function.bind if you use a bound (=>) method in a class. Both are supported in Internet Explorer 9+ and all more recent browsers, but you will need to supply polyfills if you need to support Internet Explorer 8 or below and are using features that would cause these methods to be output, or in your own code are using similarly modern methods. One option is babel-polyfill, though there are many other strategies. +To use --transpile, see Transpilation. @@ -952,8 +950,34 @@ Node.js options.filename, string: the filename to use for the source map. It can include a path (relative or absolute). options.bare, boolean: if true, output without the top-level function safety wrapper. options.header, boolean: if true, output the Generated by CoffeeScript header. +options.transpile, object: if set, this must be an object with the options to pass to Babel. See Transpilation. + + + Transpilation +CoffeeScript 2 generates JavaScript that uses the latest, modern syntax (a.k.a. ES6, or ES2015, or ES2016 or ES2017 etc.). In general, CoffeeScript 2’s output is supported as is by Node.js 7.6+, except for modules and JSX. Evergreen browsers such as the latest versions of Chrome and Safari have similar robust support. But if you want to support older browsers, or if you want to use modules or JSX, you must transpile CoffeeScript’s output. +Transpilation is the conversion of source code into equivalent but different source code. In our case, we want to convert modern JavaScript into older JavaScript that will run in older versions of Node or older browsers; for example, { a } = obj into a = obj.a. This is done via transpilers like Babel, Bublé or Traceur Compiler. +CoffeeScript includes a --transpile option when used via the coffee command, or a transpile option when used via Node. To use either, Babel must be installed in your project: +npm install --save-dev babel-core + +By default, Babel doesn’t do anything—it doesn’t make assumptions about what you want to transpile to. You might know that your code will run in Node 8, and so you want Babel to transpile modules and JSX and nothing else. Or you might want to support Internet Explorer 8, in which case Babel will transpile every feature introduced in ES2015 and later specs. +If you’re not sure what you need, a good starting point is babel-preset-env: +npm install --save-dev babel-preset-env + +See Babel’s website to learn about presets and plugins and the multitude of options you have. +Simply installing babel-preset-env isn’t enough. You also need to define the configuration options that you want Babel to use. You can do this by creating a .babelrc file in the folder containing the files you’re compiling, or in any parent folder up the path above those files. So if your project is in ~/app and your files are in ~/app/src, you can put .babelrc in either ~/app or in ~/app/src. You can also define the Babel options via a babel key in the package.json file for your project. A minimal .babelrc file (or package.json babel key) for use with babel-preset-env would be just { "presets": ["env"] }. +So to put it all together, from the root of your project: +npm install --save-dev babel-core babel-preset-env +echo '{ "presets": ["env"] }' > .babelrc + +And then you can use coffee --transpile and it will pipe CoffeeScript’s output through Babel using the options in this .babelrc file. +If you’re using CoffeeScript via the Node API, where you call CoffeeScript.compile with a string to be compiled and an options object, the transpile key of the options object should be the Babel options: +CoffeeScript.compile(code, {transpile: {presets: ['env']}}) + +You can also transpile CoffeeScript’s output without using the transpile option, for example as part of a build chain. This lets you use transpilers other than Babel, and it gives you greater control over the process. There are many great task runners for setting up JavaScript build chains, such as Gulp, Webpack, Grunt and Broccoli. +Note that babel-preset-env doesn’t automatically supply polyfills for your code. CoffeeScript itself will output Array.indexOf if you use the in operator, or destructuring or spread/rest syntax; and Function.bind if you use a bound (=>) method in a class. Both are supported in Internet Explorer 9+ and all more recent browsers, but you will need to supply polyfills if you need to support Internet Explorer 8 or below and are using features that would cause these methods to be output. You’ll also need to supply polyfills if your own code uses these methods or another method added in recent versions of JavaScript. One polyfill option is babel-polyfill, though there are many other strategies. + @@ -6030,7 +6054,7 @@
The biggest change in CoffeeScript 2 is that now the CoffeeScript compiler produces modern, ES2015+ JavaScript. A CoffeeScript => becomes an ES =>, a CoffeeScript class becomes an ES class and so on. With the exception of modules (import and export statements) and JSX, all the ES2015+ features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScript’s output without any further processing required. You can run the tests in your browser to see if your browser can do the same; Chrome has supported all features since version 55.
=>
class
import
export
Support for ES2015+ syntax is important to ensure compatibility with frameworks that assume ES2015. Now that CoffeeScript compiles classes to the ES class keyword, it’s possible to extend an ES class; that wasn’t possible in CoffeeScript 1. Parity in how language features work is also important on its own; CoffeeScript “is just JavaScript,” and so things like function parameter default values should behave the same in CoffeeScript as in JavaScript.
extend
Many ES2015+ features have been backported to CoffeeScript 1.11 and 1.12, including modules, for…of, and tagged template literals. Major new features unique to CoffeeScript 2 are support for ES2017’s async functions and for JSX. More details are in the changelog.
for…of
The biggest change in CoffeeScript 2 is that now the CoffeeScript compiler produces modern JavaScript syntax (ES6, or ES2015 and later). A CoffeeScript => becomes a JS =>, a CoffeeScript class becomes a JS class and so on. Major new features in CoffeeScript 2 include async functions and JSX. You can read more in the changelog.
There are very few breaking changes from CoffeeScript 1.x to 2; we hope the upgrade process is smooth for most projects.
CoffeeScript introduced many new features to the JavaScript world, such as => and destructuring and classes. We are happy that ECMA has seen their utility and adopted them into ECMAScript.
CoffeeScript’s intent, however, was never to be a superset of JavaScript. One of the guiding principles of CoffeeScript has been simplicity: not just removing JavaScript’s “bad parts,” but providing an elegant, concise syntax that eschews unnecessary punctuation whenever possible, to make code easier to read and reason about. This benefit of CoffeeScript remains, even in an ES2015 world.
CoffeeScript’s intent, however, was never to be a superset of JavaScript. One of the guiding principles of CoffeeScript has been simplicity: not just removing JavaScript’s “bad parts,” but providing an elegant, concise syntax that eschews unnecessary punctuation whenever possible, to make code easier to read and reason about. This benefit of CoffeeScript remains, even in an ES2015+ world.
With the exception of modules (import and export statements) and JSX, all the modern JavaScript features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScript’s output without any further processing required. You can run the tests in your browser to see if your browser can do the same. For older browsers or older versions of Node, transpilation is required.
Support for modern JavaScript syntax is important to ensure compatibility with frameworks that assume modern features. Now that CoffeeScript compiles classes to the class keyword, it’s possible to extend a JavaScript class; that wasn’t possible in CoffeeScript 1. Parity in how language features work is also important on its own; CoffeeScript “is just JavaScript,” and so things like function parameter default values should behave the same in CoffeeScript as in JavaScript. Some such features behave slightly differently in JavaScript than they did in CoffeeScript 1; in such cases we are conforming with the JavaScript spec, and we’ve documented the differences as breaking changes.
.coffee
.js
-t, --transpile
babel-core
.babelrc
package.json
babel
-m, --map
sourceMappingURL
-t, --tokens
-n, --nodes
--no-header
--nodejs
node
--debug
--debug-brk
--max-stack-size
--expose-gc
--tokens
Ctrl-D
Ctrl-V
coffee
CoffeeScript 2 outputs the latest ES2015+ syntax. If you’re looking for a single tool that takes CoffeeScript input and generates JavaScript output that runs in any JavaScript runtime, assuming you opt out of certain newer features, stick to CoffeeScript 1.x. CoffeeScript 2 breaks compatibility with certain CoffeeScript 1.x features in order to conform with the ES2015+ specifications, and generate more idiomatic output (a CoffeeScript => becomes an ES =>; a CoffeeScript class becomes an ES class; and so on).
Since the CoffeeScript 2 compiler outputs ES2015+ syntax, it is your responsibility to either ensure that your target JavaScript runtime(s) support all these features, or that you pass the output through another transpiler like Babel, Rollup or Traceur Compiler. In general, CoffeeScript 2’s output is supported as is by Node.js 7.6+, except for modules and JSX which require transpilation.
There are many great task runners for setting up JavaScript build chains, such as Gulp, Webpack, Grunt and Broccoli. If you’re looking for a very minimal solution to get started, you can use babel-preset-env and the command line:
npm install --global coffeescript@next -npm install --save-dev coffeescript@next babel-cli babel-preset-env -coffee --print *.coffee | babel --presets env > app.js - -
npm install --global coffeescript@next -npm install --save-dev coffeescript@next babel-cli babel-preset-env -coffee --print *.coffee | babel --presets env > app.js -
Note that babel-preset-env doesn’t automatically supply polyfills for your code. CoffeeScript itself will output Array.indexOf if you use the in operator, or destructuring or spread/rest syntax; and Function.bind if you use a bound (=>) method in a class. Both are supported in Internet Explorer 9+ and all more recent browsers, but you will need to supply polyfills if you need to support Internet Explorer 8 or below and are using features that would cause these methods to be output, or in your own code are using similarly modern methods. One option is babel-polyfill, though there are many other strategies.
Array.indexOf
in
Function.bind
babel-polyfill
To use --transpile, see Transpilation.
--transpile
options.filename
options.bare
options.header
Generated by CoffeeScript
options.transpile
CoffeeScript 2 generates JavaScript that uses the latest, modern syntax (a.k.a. ES6, or ES2015, or ES2016 or ES2017 etc.). In general, CoffeeScript 2’s output is supported as is by Node.js 7.6+, except for modules and JSX. Evergreen browsers such as the latest versions of Chrome and Safari have similar robust support. But if you want to support older browsers, or if you want to use modules or JSX, you must transpile CoffeeScript’s output.
Transpilation is the conversion of source code into equivalent but different source code. In our case, we want to convert modern JavaScript into older JavaScript that will run in older versions of Node or older browsers; for example, { a } = obj into a = obj.a. This is done via transpilers like Babel, Bublé or Traceur Compiler.
{ a } = obj
a = obj.a
CoffeeScript includes a --transpile option when used via the coffee command, or a transpile option when used via Node. To use either, Babel must be installed in your project:
transpile
npm install --save-dev babel-core + +
npm install --save-dev babel-core +
By default, Babel doesn’t do anything—it doesn’t make assumptions about what you want to transpile to. You might know that your code will run in Node 8, and so you want Babel to transpile modules and JSX and nothing else. Or you might want to support Internet Explorer 8, in which case Babel will transpile every feature introduced in ES2015 and later specs.
If you’re not sure what you need, a good starting point is babel-preset-env:
babel-preset-env
npm install --save-dev babel-preset-env + +
npm install --save-dev babel-preset-env +
See Babel’s website to learn about presets and plugins and the multitude of options you have.
Simply installing babel-preset-env isn’t enough. You also need to define the configuration options that you want Babel to use. You can do this by creating a .babelrc file in the folder containing the files you’re compiling, or in any parent folder up the path above those files. So if your project is in ~/app and your files are in ~/app/src, you can put .babelrc in either ~/app or in ~/app/src. You can also define the Babel options via a babel key in the package.json file for your project. A minimal .babelrc file (or package.json babel key) for use with babel-preset-env would be just { "presets": ["env"] }.
~/app
~/app/src
{ "presets": ["env"] }
So to put it all together, from the root of your project:
npm install --save-dev babel-core babel-preset-env +echo '{ "presets": ["env"] }' > .babelrc + +
npm install --save-dev babel-core babel-preset-env +echo '{ "presets": ["env"] }' > .babelrc +
And then you can use coffee --transpile and it will pipe CoffeeScript’s output through Babel using the options in this .babelrc file.
coffee --transpile
If you’re using CoffeeScript via the Node API, where you call CoffeeScript.compile with a string to be compiled and an options object, the transpile key of the options object should be the Babel options:
CoffeeScript.compile
options
CoffeeScript.compile(code, {transpile: {presets: ['env']}}) + +
CoffeeScript.compile(code, {transpile: {presets: ['env']}}) +
You can also transpile CoffeeScript’s output without using the transpile option, for example as part of a build chain. This lets you use transpilers other than Babel, and it gives you greater control over the process. There are many great task runners for setting up JavaScript build chains, such as Gulp, Webpack, Grunt and Broccoli.
Note that babel-preset-env doesn’t automatically supply polyfills for your code. CoffeeScript itself will output Array.indexOf if you use the in operator, or destructuring or spread/rest syntax; and Function.bind if you use a bound (=>) method in a class. Both are supported in Internet Explorer 9+ and all more recent browsers, but you will need to supply polyfills if you need to support Internet Explorer 8 or below and are using features that would cause these methods to be output. You’ll also need to supply polyfills if your own code uses these methods or another method added in recent versions of JavaScript. One polyfill option is babel-polyfill, though there are many other strategies.