From 37e6513c02891c45e7633f67c9b89b993b2d6f4d Mon Sep 17 00:00:00 2001 From: Geoffrey Date: Mon, 13 Feb 2017 20:31:58 -0800 Subject: [PATCH 1/9] =?UTF-8?q?Node=20comes=20with=20NPM=20nowadays,=20so?= =?UTF-8?q?=20there=E2=80=99s=20not=20really=20a=20reason=20to=20install?= =?UTF-8?q?=20CoffeeScript=20the=20non-NPM=20way?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cakefile | 21 --------------------- README.md | 11 +++-------- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/Cakefile b/Cakefile index 61d46227b1..56714f5e92 100644 --- a/Cakefile +++ b/Cakefile @@ -45,27 +45,6 @@ run = (args, cb) -> log = (message, color, explanation) -> console.log color + message + reset + ' ' + (explanation or '') -option '-p', '--prefix [DIR]', 'set the installation prefix for `cake install`' - -task 'install', 'install CoffeeScript into /usr/local (or --prefix)', (options) -> - base = options.prefix or '/usr/local' - lib = "#{base}/lib/coffee-script" - bin = "#{base}/bin" - node = "~/.node_libraries/coffee-script" - console.log "Installing CoffeeScript to #{lib}" - console.log "Linking to #{node}" - console.log "Linking 'coffee' to #{bin}/coffee" - exec([ - "mkdir -p #{lib} #{bin}" - "cp -rf bin lib LICENSE README.md package.json src #{lib}" - "ln -sfn #{lib}/bin/coffee #{bin}/coffee" - "ln -sfn #{lib}/bin/cake #{bin}/cake" - "mkdir -p ~/.node_libraries" - "ln -sfn #{lib}/lib/coffee-script #{node}" - ].join(' && '), (err, stdout, stderr) -> - if err then console.log stderr.trim() else log 'done', green - ) - task 'build', 'build the CoffeeScript language from source', build diff --git a/README.md b/README.md index 486d7d26db..432c83ce2d 100644 --- a/README.md +++ b/README.md @@ -25,15 +25,10 @@ CoffeeScript is a little language that compiles into JavaScript. If you have the node package manager, npm, installed: ```shell -npm install -g coffee-script +npm install --global coffee-script ``` -Leave off the `-g` if you don't wish to install globally. If you don't wish to use npm: - -```shell -git clone https://github.com/jashkenas/coffeescript.git -sudo coffeescript/bin/cake install -``` +Leave off the `--global` if you don’t wish to install globally. ## Getting Started @@ -53,7 +48,7 @@ For documentation, usage, and examples, see: http://coffeescript.org/ To suggest a feature or report a bug: http://github.com/jashkenas/coffeescript/issues -If you'd like to chat, drop by #coffeescript on Freenode IRC. +If you’d like to chat, drop by #coffeescript on Freenode IRC. The source repository: https://github.com/jashkenas/coffeescript.git From c06a0584ff7c95f282d6eef8f7123135d56efcbf Mon Sep 17 00:00:00 2001 From: Geoffrey Date: Mon, 13 Feb 2017 20:42:13 -0800 Subject: [PATCH 2/9] The cake documentation tasks should each have build and watch modes following the same form --- Cakefile | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/Cakefile b/Cakefile index 56714f5e92..da176a8d4b 100644 --- a/Cakefile +++ b/Cakefile @@ -117,7 +117,7 @@ task 'build:browser', 'rebuild the merged script for inclusion in the browser', invoke 'test:browser' -task 'doc:site', 'watch and continually rebuild the documentation for the website', -> +buildDocs = (watch = no) -> # Constants indexFile = 'documentation/index.html' versionedSourceFolder = "documentation/v#{majorVersion}" @@ -190,12 +190,19 @@ task 'doc:site', 'watch and continually rebuild the documentation for the websit fs.symlinkSync "v#{majorVersion}/index.html", 'docs/index.html' catch exception - for target in [indexFile, versionedSourceFolder, examplesSourceFolder, sectionsSourceFolder] - fs.watch target, interval: 200, renderIndex - log 'watching...' , green + if watch + for target in [indexFile, versionedSourceFolder, examplesSourceFolder, sectionsSourceFolder] + fs.watch target, interval: 200, renderIndex + log 'watching...' , green +task 'doc:site', 'build the documentation for the website', -> + buildDocs() -task 'doc:test', 'watch and continually rebuild the browser-based tests', -> +task 'doc:site:watch', 'watch and continually rebuild the documentation for the website', -> + buildDocs yes + + +buildDocTests = (watch = no) -> # Constants testFile = 'documentation/test.html' testsSourceFolder = 'test' @@ -233,13 +240,32 @@ task 'doc:test', 'watch and continually rebuild the browser-based tests', -> fs.writeFileSync "#{outputFolder}/test.html", output log 'compiled', green, "#{testFile} → #{outputFolder}/test.html" - for target in [testFile, testsSourceFolder] - fs.watch target, interval: 200, renderTest - log 'watching...' , green + if watch + for target in [testFile, testsSourceFolder] + fs.watch target, interval: 200, renderTest + log 'watching...' , green + +task 'doc:test', 'build the browser-based tests', -> + buildDocTests() + +task 'doc:test:watch', 'watch and continually rebuild the browser-based tests', -> + buildDocTests yes + + +buildAnnotatedSource = (watch = no) -> + do generateAnnotatedSource = -> + exec "node_modules/docco/bin/docco src/*.*coffee --output docs/v#{majorVersion}/annotated-source", (err) -> throw err if err + log 'generated', green, "annotated source in docs/v#{majorVersion}/annotated-source/" + + if watch + fs.watch 'src/', interval: 200, generateAnnotatedSource + log 'watching...' , green +task 'doc:source', 'build the annotated source documentation', -> + buildAnnotatedSource() -task 'doc:source', 'rebuild the annotated source documentation', -> - exec "node_modules/docco/bin/docco src/*.*coffee --output docs/v#{majorVersion}/annotated-source", (err) -> throw err if err +task 'doc:source:watch', 'watch and continually rebuild the annotated source documentation', -> + buildAnnotatedSource yes task 'bench', 'quick benchmark of compilation time', -> From 8a271995c7d663a6e21e61637bfdbac799c69c57 Mon Sep 17 00:00:00 2001 From: Geoffrey Date: Mon, 13 Feb 2017 21:05:12 -0800 Subject: [PATCH 3/9] =?UTF-8?q?Refactor=20the=20build=20tasks=20to=20be=20?= =?UTF-8?q?more=20foolproof,=20including=20the=20parser=20unless=20it?= =?UTF-8?q?=E2=80=99s=20explicitly=20excluded?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cakefile | 49 +++++++++++++++++------------ docs/v1/index.html | 6 ++-- documentation/sections/resources.md | 6 ++-- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/Cakefile b/Cakefile index da176a8d4b..be742734c7 100644 --- a/Cakefile +++ b/Cakefile @@ -24,15 +24,34 @@ header = """ */ """ -# Used in folder names like docs/v1 +# Used in folder names like `docs/v1`. majorVersion = parseInt CoffeeScript.VERSION.split('.')[0], 10 + # Build the CoffeeScript language from source. -build = (cb) -> +buildParser = -> + helpers.extend global, require 'util' + require 'jison' + parser = require('./lib/coffee-script/grammar').parser.generate() + # Patch Jison’s output, until https://github.com/zaach/jison/pull/339 is accepted, + # to ensure that require('fs') is only called where it exists. + parser = parser.replace "var source = require('fs')", """ + var source = ''; + var fs = require('fs'); + if (typeof fs !== 'undefined' && fs !== null) + source = fs""" + fs.writeFileSync 'lib/coffee-script/parser.js', parser + +buildExceptParser = (cb) -> files = fs.readdirSync 'src' files = ('src/' + file for file in files when file.match(/\.(lit)?coffee$/)) run ['-c', '-o', 'lib/coffee-script'].concat(files), cb +build = (cb) -> + buildParser() + buildExceptParser cb + + # Run a CoffeeScript through our node/coffee interpreter. run = (args, cb) -> proc = spawn 'node', ['bin/coffee'].concat(args) @@ -41,14 +60,19 @@ run = (args, cb) -> process.exit(1) if status isnt 0 cb() if typeof cb is 'function' + # Log a message with a color. log = (message, color, explanation) -> console.log color + message + reset + ' ' + (explanation or '') -task 'build', 'build the CoffeeScript language from source', build +task 'build', 'build the CoffeeScript compiler from source', build + +task 'build:parser', 'build the Jison parser only', buildParser + +task 'build:except-parser', 'build the CoffeeScript compiler, except for the Jison parser', buildExceptParser -task 'build:full', 'rebuild the source twice, and run the tests', -> +task 'build:full', 'build the CoffeeScript compiler from source twice, and run the tests', -> build -> build -> csPath = './lib/coffee-script' @@ -60,22 +84,7 @@ task 'build:full', 'rebuild the source twice, and run the tests', -> unless runTests require csPath process.exit 1 - -task 'build:parser', 'rebuild the Jison parser (run build first)', -> - helpers.extend global, require 'util' - require 'jison' - parser = require('./lib/coffee-script/grammar').parser.generate() - # Patch Jison’s output, until https://github.com/zaach/jison/pull/339 is accepted, - # to ensure that require('fs') is only called where it exists. - parser = parser.replace "var source = require('fs')", """ - var source = ''; - var fs = require('fs'); - if (typeof fs !== 'undefined' && fs !== null) - source = fs""" - fs.writeFileSync 'lib/coffee-script/parser.js', parser - - -task 'build:browser', 'rebuild the merged script for inclusion in the browser', -> +task 'build:browser', 'build the merged script for inclusion in the browser', -> code = """ require['../../package.json'] = (function() { return #{fs.readFileSync "./package.json"}; diff --git a/docs/v1/index.html b/docs/v1/index.html index c108e6d015..0cd03d5495 100644 --- a/docs/v1/index.html +++ b/docs/v1/index.html @@ -2584,9 +2584,9 @@

Resources

  • Source Code
    Use bin/coffee to test your changes,
    bin/cake test to run the test suite,
    -bin/cake build to rebuild the CoffeeScript compiler, and
    -bin/cake build:parser to regenerate the Jison parser if you’re working on the grammar.

    -

    git checkout lib && bin/cake build:full is a good command to run when you’re working on the core language. It’ll refresh the lib directory (in case you broke something), build your altered compiler, use that to rebuild itself (a good sanity test) and then run all of the tests. If they pass, there’s a good chance you’ve made a successful change.

    +bin/cake build to rebuild the full CoffeeScript compiler, and
    +bin/cake build:except-parser to recompile much faster if you’re not editing grammar.coffee.

    +

    git checkout lib && bin/cake build:full is a good command to run when you’re working on the core language. It’ll refresh the lib folder (in case you broke something), build your altered compiler, use that to rebuild itself (a good sanity test) and then run all of the tests. If they pass, there’s a good chance you’ve made a successful change.

  • Browser Tests
    Run CoffeeScript’s test suite in your current browser.
  • diff --git a/documentation/sections/resources.md b/documentation/sections/resources.md index 9e1e2927a0..bac559e4ee 100644 --- a/documentation/sections/resources.md +++ b/documentation/sections/resources.md @@ -3,10 +3,10 @@ * [Source Code](http://github.com/jashkenas/coffeescript/)
    Use `bin/coffee` to test your changes,
    `bin/cake test` to run the test suite,
    - `bin/cake build` to rebuild the CoffeeScript compiler, and
    - `bin/cake build:parser` to regenerate the Jison parser if you’re working on the grammar. + `bin/cake build` to rebuild the full CoffeeScript compiler, and
    + `bin/cake build:except-parser` to recompile much faster if you’re not editing `grammar.coffee`. - `git checkout lib && bin/cake build:full` is a good command to run when you’re working on the core language. It’ll refresh the lib directory (in case you broke something), build your altered compiler, use that to rebuild itself (a good sanity test) and then run all of the tests. If they pass, there’s a good chance you’ve made a successful change. + `git checkout lib && bin/cake build:full` is a good command to run when you’re working on the core language. It’ll refresh the `lib` folder (in case you broke something), build your altered compiler, use that to rebuild itself (a good sanity test) and then run all of the tests. If they pass, there’s a good chance you’ve made a successful change. * [Browser Tests](v<%= majorVersion %>/test.html)
    Run CoffeeScript’s test suite in your current browser. * [CoffeeScript Issues](http://github.com/jashkenas/coffeescript/issues)
    From 9866224dba1424b9a3bece0bfc36739e540a343c Mon Sep 17 00:00:00 2001 From: Geoffrey Date: Mon, 13 Feb 2017 21:49:04 -0800 Subject: [PATCH 4/9] Abstract out testing built code, to prepare for watching the build task --- Cakefile | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/Cakefile b/Cakefile index be742734c7..bbf6f34f7f 100644 --- a/Cakefile +++ b/Cakefile @@ -51,6 +51,17 @@ build = (cb) -> buildParser() buildExceptParser cb +testBuiltCode = (watch = no) -> + csPath = './lib/coffee-script' + csDir = path.dirname require.resolve csPath + + for mod of require.cache when csDir is mod[0 ... csDir.length] + delete require.cache[mod] + + testResults = runTests require csPath + unless watch + process.exit 1 unless testResults + # Run a CoffeeScript through our node/coffee interpreter. run = (args, cb) -> @@ -74,15 +85,7 @@ task 'build:except-parser', 'build the CoffeeScript compiler, except for the Jis task 'build:full', 'build the CoffeeScript compiler from source twice, and run the tests', -> build -> - build -> - csPath = './lib/coffee-script' - csDir = path.dirname require.resolve csPath - - for mod of require.cache when csDir is mod[0 ... csDir.length] - delete require.cache[mod] - - unless runTests require csPath - process.exit 1 + build testBuiltCode task 'build:browser', 'build the merged script for inclusion in the browser', -> code = """ @@ -202,7 +205,7 @@ buildDocs = (watch = no) -> if watch for target in [indexFile, versionedSourceFolder, examplesSourceFolder, sectionsSourceFolder] fs.watch target, interval: 200, renderIndex - log 'watching...' , green + log 'watching...', green task 'doc:site', 'build the documentation for the website', -> buildDocs() @@ -252,7 +255,7 @@ buildDocTests = (watch = no) -> if watch for target in [testFile, testsSourceFolder] fs.watch target, interval: 200, renderTest - log 'watching...' , green + log 'watching...', green task 'doc:test', 'build the browser-based tests', -> buildDocTests() @@ -268,7 +271,7 @@ buildAnnotatedSource = (watch = no) -> if watch fs.watch 'src/', interval: 200, generateAnnotatedSource - log 'watching...' , green + log 'watching...', green task 'doc:source', 'build the annotated source documentation', -> buildAnnotatedSource() From f4a1172b6f019e4602169202162d085cb2e7aaa0 Mon Sep 17 00:00:00 2001 From: Geoffrey Date: Mon, 13 Feb 2017 21:58:23 -0800 Subject: [PATCH 5/9] Cake task to cut a new release --- Cakefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Cakefile b/Cakefile index bbf6f34f7f..5d1a9bcabd 100644 --- a/Cakefile +++ b/Cakefile @@ -280,6 +280,13 @@ task 'doc:source:watch', 'watch and continually rebuild the annotated source doc buildAnnotatedSource yes +task 'release', 'build and test the CoffeeScript source, and build the documentation', -> + invoke 'build:full' + invoke 'build:browser' + invoke 'doc:site' + invoke 'doc:test' + invoke 'doc:source' + task 'bench', 'quick benchmark of compilation time', -> {Rewriter} = require './lib/coffee-script/rewriter' sources = ['coffee-script', 'grammar', 'helpers', 'lexer', 'nodes', 'rewriter'] From 856bf5e68c6dfeb8040f69db0aa7c6aa5ccd2436 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Tue, 14 Feb 2017 19:13:41 -0800 Subject: [PATCH 6/9] cake build:watch, based on https://github.com/GeoffreyBooth/coffeescript-gulp --- Cakefile | 72 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/Cakefile b/Cakefile index 5d1a9bcabd..3066a1b8d9 100644 --- a/Cakefile +++ b/Cakefile @@ -28,6 +28,25 @@ header = """ majorVersion = parseInt CoffeeScript.VERSION.split('.')[0], 10 +# Log a message with a color. +log = (message, color, explanation) -> + console.log color + message + reset + ' ' + (explanation or '') + + +spawnNodeProcess = (args, output = 'stderr', callback) -> + relayOutput = (buffer) -> console.log buffer.toString() + proc = spawn 'node', args + proc.stdout.on 'data', relayOutput if output is 'both' or output is 'stdout' + proc.stderr.on 'data', relayOutput if output is 'both' or output is 'stderr' + proc.on 'exit', (status) -> callback(status) if typeof callback is 'function' + +# Run a CoffeeScript through our node/coffee interpreter. +run = (args, callback) -> + spawnNodeProcess ['bin/coffee'].concat(args), 'stderr', (status) -> + process.exit(1) if status isnt 0 + callback() if typeof callback is 'function' + + # Build the CoffeeScript language from source. buildParser = -> helpers.extend global, require 'util' @@ -42,14 +61,14 @@ buildParser = -> source = fs""" fs.writeFileSync 'lib/coffee-script/parser.js', parser -buildExceptParser = (cb) -> +buildExceptParser = (callback) -> files = fs.readdirSync 'src' files = ('src/' + file for file in files when file.match(/\.(lit)?coffee$/)) - run ['-c', '-o', 'lib/coffee-script'].concat(files), cb + run ['-c', '-o', 'lib/coffee-script'].concat(files), callback -build = (cb) -> +build = (callback) -> buildParser() - buildExceptParser cb + buildExceptParser callback testBuiltCode = (watch = no) -> csPath = './lib/coffee-script' @@ -62,19 +81,32 @@ testBuiltCode = (watch = no) -> unless watch process.exit 1 unless testResults - -# Run a CoffeeScript through our node/coffee interpreter. -run = (args, cb) -> - proc = spawn 'node', ['bin/coffee'].concat(args) - proc.stderr.on 'data', (buffer) -> console.log buffer.toString() - proc.on 'exit', (status) -> - process.exit(1) if status isnt 0 - cb() if typeof cb is 'function' - - -# Log a message with a color. -log = (message, color, explanation) -> - console.log color + message + reset + ' ' + (explanation or '') +buildAndTest = (includingParser = yes, harmony = no) -> + process.stdout.write '\x1Bc' # Clear terminal screen. + execSync 'git checkout lib/*', stdio: [0,1,2] # Reset the generated compiler. + + buildArgs = ['bin/cake'] + buildArgs.push if includingParser then 'build' else 'build:except-parser' + log "building#{if includingParser then ', including parser' else ''}...", green + spawnNodeProcess buildArgs, 'both', -> + log 'testing...', green + testArgs = if harmony then ['--harmony'] else [] + testArgs = testArgs.concat ['bin/cake', 'test'] + spawnNodeProcess testArgs, 'both' + +watchAndBuildAndTest = (harmony = no) -> + buildAndTest yes, harmony + fs.watch 'src/', interval: 200, (eventType, filename) -> + if eventType is 'change' + log "src/#{filename} changed, rebuilding..." + buildAndTest (filename is 'grammar.coffee'), harmony + fs.watch 'test/', + interval: 200 + recursive: yes + , (eventType, filename) -> + if eventType is 'change' + log "test/#{filename} changed, rebuilding..." + buildAndTest no, harmony task 'build', 'build the CoffeeScript compiler from source', build @@ -128,6 +160,12 @@ task 'build:browser', 'build the merged script for inclusion in the browser', -> console.log "built ... running browser tests:" invoke 'test:browser' +task 'build:watch', 'watch and continually rebuild the CoffeeScript compiler, running tests on each build', -> + watchAndBuildAndTest() + +task 'build:watch:harmony', 'watch and continually rebuild the CoffeeScript compiler, running harmony tests on each build', -> + watchAndBuildAndTest yes + buildDocs = (watch = no) -> # Constants From c29a663e9cd838fc73f3c15213927ec523f2746e Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Fri, 17 Feb 2017 12:13:03 -0500 Subject: [PATCH 7/9] Coding style --- Cakefile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Cakefile b/Cakefile index 3066a1b8d9..d002ccb48b 100644 --- a/Cakefile +++ b/Cakefile @@ -100,10 +100,7 @@ watchAndBuildAndTest = (harmony = no) -> if eventType is 'change' log "src/#{filename} changed, rebuilding..." buildAndTest (filename is 'grammar.coffee'), harmony - fs.watch 'test/', - interval: 200 - recursive: yes - , (eventType, filename) -> + fs.watch 'test/', {interval: 200, recursive: yes}, (eventType, filename) -> if eventType is 'change' log "test/#{filename} changed, rebuilding..." buildAndTest no, harmony From 279c2fff828fd19dbb2d8c3cf342ca75adf72f97 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Fri, 17 Feb 2017 13:51:00 -0500 Subject: [PATCH 8/9] =?UTF-8?q?Tests=20shouldn=E2=80=99t=20write=20files?= =?UTF-8?q?=20in=20a=20watched=20folder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/error_messages.coffee | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/test/error_messages.coffee b/test/error_messages.coffee index f7f4a928cd..e3a07e98c7 100644 --- a/test/error_messages.coffee +++ b/test/error_messages.coffee @@ -71,20 +71,21 @@ if require? test "#2849: compilation error in a require()d file", -> # Create a temporary file to require(). - ok not fs.existsSync 'test/syntax-error.coffee' - fs.writeFileSync 'test/syntax-error.coffee', 'foo in bar or in baz' + tempFile = path.join os.tmpdir(), 'syntax-error.coffee' + ok not fs.existsSync tempFile + fs.writeFileSync tempFile, 'foo in bar or in baz' try - assertErrorFormat ''' - require './test/syntax-error' - ''', + assertErrorFormat """ + require '#{tempFile}' + """, """ - #{path.join __dirname, 'syntax-error.coffee'}:1:15: error: unexpected in + #{fs.realpathSync tempFile}:1:15: error: unexpected in foo in bar or in baz ^^ """ finally - fs.unlinkSync 'test/syntax-error.coffee' + fs.unlinkSync tempFile test "#3890 Error.prepareStackTrace doesn't throw an error if a compiled file is deleted", -> # Adapted from https://github.com/atom/coffee-cash/blob/master/spec/coffee-cash-spec.coffee From 8817dec16145e0e6e66fe12e021ab53e196e5605 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Sat, 18 Feb 2017 02:34:02 -0500 Subject: [PATCH 9/9] =?UTF-8?q?Don=E2=80=99t=20crash=20if=20the=20REPL=20t?= =?UTF-8?q?est=20history=20file=20is=20already=20gone=20by=20the=20time=20?= =?UTF-8?q?we=20try=20to=20delete=20it?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/repl.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/repl.coffee b/test/repl.coffee index 4f0d870094..6a4d900c38 100644 --- a/test/repl.coffee +++ b/test/repl.coffee @@ -109,4 +109,6 @@ testRepl "keeps running after runtime error", (input, output) -> eq 'undefined', output.lastWrite() process.on 'exit', -> - fs.unlinkSync historyFile + try + fs.unlinkSync historyFile + catch exception # Already deleted, nothing else to do.