Compare commits

..

185 Commits
2.3.2 ... 2.7.0

Author SHA1 Message Date
Geoffrey Booth
b51361abe7 Update package-lock.json 2022-04-23 19:27:52 -07:00
Geoffrey Booth
519248fc7d 2.7.0 (#5412) 2022-04-23 19:19:19 -07:00
Geoffrey Booth
6b4f166eb9 Add patchStackTrace export; test that all named exports are detected by Node (#5411) 2022-04-19 09:58:30 -07:00
Geoffrey Booth
4f365524d7 Update output 2022-04-19 09:03:13 -07:00
Daniel X Moore
8d32c713c5 Don’t patch Error.prepareStackTrace if --enable-source-maps is used. (#5403)
Co-authored-by: Geoffrey Booth <456802+GeoffreyBooth@users.noreply.github.com>
2022-04-18 20:10:55 -07:00
Daniel X Moore
76cf769abf Report browser test errors (#5408) 2022-04-05 16:32:26 -07:00
Daniel X Moore
44bf59923e Remove always true if check (#5406) 2022-04-04 14:39:16 -07:00
Geoffrey Booth
d535a78e32 Update dependencies (#5405) 2022-04-02 20:00:56 -07:00
Daniel X Moore
3ad26de8f0 Fix CI for Node 16.14.x (#5404)
Co-authored-by: Geoffrey Booth <webadmin@geoffreybooth.com>
2022-04-02 16:53:05 -07:00
Erik Demaine
3d39d205d8 Fix continuing first line of explicit [/{ literal (#5397) 2022-01-26 09:29:01 -08:00
Erik Demaine
6fd58ef11c CI: Ensure browser tests are up-to-date (#5396) 2022-01-25 06:40:48 -08:00
Geoffrey Booth
f557c0579b Import assertions (#5391) 2022-01-20 11:40:13 -08:00
Jeremy Ashkenas
20b8362887 Empty commit to rebuilt github pages 2022-01-17 11:22:33 -08:00
Daniel Bayley
726c0858e4 Add Integrations section to docs (#5334)
Co-authored-by: Geoffrey Booth <webadmin@geoffreybooth.com>
2021-11-29 11:04:47 -08:00
Julian Rosse
887a6174e9 Handle triple-quoted JSX attribute values (#5353)
Co-authored-by: Geoffrey Booth <webadmin@geoffreybooth.com>
2021-11-26 20:26:02 -08:00
Geoffrey Booth
ed6733d177 2.6.1 (#5381) 2021-10-04 20:50:11 -07:00
Geoffrey Booth
d572d744eb Fix #5378, stack overflow on large files (#5380) 2021-10-02 16:24:32 -07:00
Geoffrey Booth
e82de9c0f6 Named exports for Node ESM for coffeescript package (#5376) 2021-09-20 22:05:41 -07:00
Erik Demaine
f5073fa132 Improve documentation of jumps in comments (#5375)
* Improve documentation of jumps

* Review suggestion

Co-authored-by: Geoffrey Booth <456802+GeoffreyBooth@users.noreply.github.com>

* Rebuild

Co-authored-by: Geoffrey Booth <456802+GeoffreyBooth@users.noreply.github.com>
2021-09-19 22:53:48 -07:00
Geoffrey Booth
f9c3316aa5 2.6.0 (#5374) 2021-09-19 14:15:00 -07:00
Erik Demaine
ff13d85625 ci: Check that build steps didn’t change any files (#5373) 2021-09-16 15:04:51 -07:00
Erik Demaine
c4f1fe7132 Support top-level await (#5371)
* Support top-level await

* Remove code duplication

* Avoid use of trimEnd so tests pass in old Node

* Proposed rewrite of tests

* startsWith tests; revert eqJS

* build:browser
2021-09-15 10:40:18 -07:00
Erik Demaine
b0946c3c60 Fix documentation links to try/catch section (#5349)
* Fix documentation links to try/catch section

Consistently use `#try-catch` for the section (and `#try` for the demo)

* Fix documentation source
2021-09-15 10:39:38 -07:00
Geoffrey Booth
b90bc2459a Add Node 16 to CI (#5372) 2021-09-14 21:39:11 -07:00
Geoffrey Booth
07f644c392 Fix call MetaProperty (#5324) 2020-06-02 21:00:40 -07:00
Aurélio A. Heckert
2fd9ee403c Support import.meta and import.meta.* (#5319)
Co-authored-by: Geoffrey Booth <webmaster@geoffreybooth.com>
2020-05-29 18:16:48 -07:00
Geoffrey Booth
389ce89555 Run browser tests in headless Chrome; replace Travis and AppVeyor with GitHub Actions (#5298) 2020-05-25 21:03:49 -07:00
Julian Rosse
75d376f2ef Fix: comprehension as postfix conditional (#5310)
Co-authored-by: Geoffrey Booth <webmaster@geoffreybooth.com>
2020-03-10 10:29:00 -07:00
Geoffrey Booth
3136bde928 Update dependencies (#5311)
* Install exactly @babel/core@7.7.7, the last version known to work in Node 6 --harmony

* Update other dependencies
2020-03-10 00:28:54 -07:00
Geoffrey Booth
26a7ba1659 2.5.1 (#5297)
* Bump version to 2.5.1

* Changelog for 2.5.1

* Update output for 2.5.1
2020-01-30 22:38:10 -08:00
Julian Rosse
9cef39d21a Handle implicit object as end of outer implicit object property value (#5296)
* not continuing implicit object if after UNFINISHED

* following property not working

* handle following object properties

* tests

* indebt -> continuationLineAdditionalIndent
2020-01-29 16:20:40 -08:00
Julian Rosse
92ad04b9b1 Allow soaks and prototype shorthands in object splats (#5293)
* use normal Accessor grammar rule

* allow soaked calls

* test lhs spread
2020-01-27 15:37:22 -08:00
Julian Rosse
6fe980e569 Improve performance of location data compensation (#5294) 2020-01-26 22:46:28 -08:00
Daniel Bayley
bb8df1e052 Fix typos (#5287) 2020-01-16 09:54:12 -08:00
Geoffrey Booth
61d408f093 2.5.0 (#5284)
* 2.5.0 changelog

* Update dependencies

* Colors are expected to be globals by the new AST test helpers

* Disable testing of deepStrictIncludeExpectedProperties in browsers for now

* Update output of compiler only

* Update browser compiler output

* Update docs output

* Document ast option

* Update output

* Fix and reenable deepStrict test for browser test suite

* Update output
2019-12-31 22:19:32 -08:00
Julian Rosse
ba41b4417d Allow linebreak/indent in destructured for variable (#5286)
* allow linebreak/indent in for variable pattern

* tests

* <

* condition
2019-12-31 18:22:04 -08:00
Geoffrey Booth
33bbef963c Merge pull request #5285 from helixbass/browser-compiler-call-parsing-error
Browser compiler call parsing fix
2019-12-31 09:58:04 -08:00
Julian Rosse
c4f0c9ed06 don't return boolean from grammar rule 2019-12-31 10:05:42 -07:00
Geoffrey Booth
8677a0dbc4 Update output from #5275 2019-12-30 23:17:55 -08:00
Geoffrey Booth
ee2a107f3c AST: Refactor marking nodes that return (#5275)
AST: Refactor marking nodes that return
2019-12-30 12:57:50 -08:00
Geoffrey Booth
8fb5c1ba4f Make it clearer that we're adding a property to an object 2019-12-30 09:54:06 -08:00
Geoffrey Booth
b2b2f97873 Fix comments after colons getting lost (#5276)
Fix comments after colons getting lost
2019-12-30 07:21:15 -08:00
Geoffrey Booth
0045cb21ba Colons are apparently another token type that doesn't survive passing through the parser, so rescue any comments attached to colons 2019-12-30 01:04:30 -08:00
Geoffrey Booth
a8273bf980 No need for separate ast returns method, as it's never overridden 2019-12-29 23:10:30 -08:00
Geoffrey Booth
3e7c570679 AST (#5273)
AST
2019-12-29 22:31:05 -08:00
Julian Rosse
a34c0c9502 Return Root from nodes() (#5274)
* return Root from nodes()

* add children
2019-12-29 21:17:32 -08:00
Geoffrey Booth
2ab714b4fe Merge branch 'master' into ast
# Conflicts:
#	lib/coffeescript/lexer.js
#	lib/coffeescript/parser.js
#	src/lexer.coffee
#	test/jsx.coffee
#	test/numeric_literal_separators.coffee
2019-12-29 17:00:06 -08:00
Geoffrey Booth
56eec0bc4e AST: Update with latest changes from master (#5270)
* Fix #5213: Update Babel options to restore MINIFY=false (#5214)

* CSX namespaced tags and attributes (#5218)

* Support namespaces in attributes

* Support namespaces in tag names

* Support reserved words in CSX boolean properties (fix #5125)

* Implement review comments

* Build

* Revert parser.js

* Add debugging information to error message test (#5239)

One of the test cases in test/error_messages.coffee fails intermittently
in the Node.js ecosystem-testing tool CITGM. In an effort to help debug
what's going on when this occurs, this adds more information to the
AssertionError message in question.

* Fix #5103: Add support for BigInt literals (#5104)

* Fix #5103: Add support for BigInt literals

* Fix typos found in testing

* Support binary, octal and hex BigInt literals

* Make decimal BigInt test consistent other bases

* Correct test BigInt test names

* Add Node versions to CI

* Numeric literal separators (#5215)

* implement numeric literal separators

* add tests

* Revert changes to package-lock.json

* small regex adjustment

* split tests

* add comment

* Add Node versions to CI

* Fix #5103: Add support for BigInt literals (#5104)

* Fix #5103: Add support for BigInt literals

* Fix typos found in testing

* Support binary, octal and hex BigInt literals

* Make decimal BigInt test consistent other bases

* Correct test BigInt test names

* Add Node versions to CI

* Update output

* Fix style

* support bigint literal with separators

* un-disallow property access on number literal

* Update output

* Refactor numeric literal separator tests to be more like the rest of the tests

* Add test for numeric property with underscore

Co-authored-by: Geoffrey Booth <GeoffreyBooth@users.noreply.github.com>
Co-authored-by: Robert de Forest <guitar.robot@gmail.com>

Co-authored-by: Erik Demaine <edemaine@mit.edu>
Co-authored-by: Rich Trott <rtrott@gmail.com>
Co-authored-by: Robert de Forest <guitar.robot@gmail.com>
Co-authored-by: square <Inve1951@users.noreply.github.com>
2019-12-29 16:55:33 -08:00
Julian Rosse
f528e5e754 AST: numeric separators, BigInt (#5272)
* Revert to more complicated lexing of numbers, as the Number constructor can't handle BigInts or numbers with numeric separators

* Add debugging information to error message test (#5239)

One of the test cases in test/error_messages.coffee fails intermittently
in the Node.js ecosystem-testing tool CITGM. In an effort to help debug
what's going on when this occurs, this adds more information to the
AssertionError message in question.

* Fix #5103: Add support for BigInt literals (#5104)

* Fix #5103: Add support for BigInt literals

* Fix typos found in testing

* Support binary, octal and hex BigInt literals

* Make decimal BigInt test consistent other bases

* Correct test BigInt test names

* Add Node versions to CI

* Numeric literal separators (#5215)

* implement numeric literal separators

* add tests

* Revert changes to package-lock.json

* small regex adjustment

* split tests

* add comment

* Add Node versions to CI

* Fix #5103: Add support for BigInt literals (#5104)

* Fix #5103: Add support for BigInt literals

* Fix typos found in testing

* Support binary, octal and hex BigInt literals

* Make decimal BigInt test consistent other bases

* Correct test BigInt test names

* Add Node versions to CI

* Update output

* Fix style

* support bigint literal with separators

* un-disallow property access on number literal

* Update output

* Refactor numeric literal separator tests to be more like the rest of the tests

* Add test for numeric property with underscore

Co-authored-by: Geoffrey Booth <GeoffreyBooth@users.noreply.github.com>
Co-authored-by: Robert de Forest <guitar.robot@gmail.com>

* Update test style and output

* numeric separator parsed value

* BigInt AST; parseNumber()

Co-authored-by: Geoffrey Booth <GeoffreyBooth@users.noreply.github.com>
Co-authored-by: Rich Trott <rtrott@gmail.com>
Co-authored-by: Robert de Forest <guitar.robot@gmail.com>
Co-authored-by: square <Inve1951@users.noreply.github.com>
2019-12-29 16:20:43 -08:00
Geoffrey Booth
bdcb2c73af Revert to more complicated lexing of numbers, as the Number constructor can't handle BigInts or numbers with numeric separators (#5269) 2019-12-29 15:41:01 -08:00
square
9b37f16f11 Numeric literal separators (#5215)
* implement numeric literal separators

* add tests

* Revert changes to package-lock.json

* small regex adjustment

* split tests

* add comment

* Add Node versions to CI

* Fix #5103: Add support for BigInt literals (#5104)

* Fix #5103: Add support for BigInt literals

* Fix typos found in testing

* Support binary, octal and hex BigInt literals

* Make decimal BigInt test consistent other bases

* Correct test BigInt test names

* Add Node versions to CI

* Update output

* Fix style

* support bigint literal with separators

* un-disallow property access on number literal

* Update output

* Refactor numeric literal separator tests to be more like the rest of the tests

* Add test for numeric property with underscore

Co-authored-by: Geoffrey Booth <GeoffreyBooth@users.noreply.github.com>
Co-authored-by: Robert de Forest <guitar.robot@gmail.com>
2019-12-28 17:02:40 -08:00
Julian Rosse
26351096a6 AST: interpolated string is computed key (#5267)
* interpolated string key is computed

* lhs test
2019-12-22 15:47:24 -08:00
Julian Rosse
a091bb82f9 AST: splat param location data (#5266)
* handle assignment to nested nontrailing splat

* splat param location data
2019-12-17 23:19:09 -08:00
Julian Rosse
a6d4bf1982 handle assignment to nested nontrailing splat (#5265) 2019-12-17 23:18:27 -08:00
Julian Rosse
0e51cdaccd AST: allow assignment to nontrailing splat (#5263)
* allow assignment to nontrailing splat

* allow assignment to empty array

* complex object splat

* add explanatory comment
2019-12-16 17:18:26 -08:00
Julian Rosse
d4b7bd3a1f AST: fix interpolated regex tokens (#5262)
* this property

* clean up AST tests

* updated grammar

* export location data

* export default class location data

* fix interpolated regex tokens
2019-12-16 14:14:23 -08:00
Julian Rosse
559e735994 AST: clean up AST tests (#5261)
* this property

* clean up AST tests

* updated grammar

* export location data

* export default class location data
2019-12-16 14:13:54 -08:00
Julian Rosse
09caa217c2 AST: test compile errors (#5260)
* multiple splats error

* delete operand; catch variable

* disallow multiple splats

* unassignable conditional

* lone expansion param

* class bodies pure statements/arguments

* remove duplicate

* getAndCheckSplatProps()

* getAndCheckSplatsAndExpansions()

* clean up disallowLoneExpansionAndMultipleSplats()
2019-12-16 00:16:55 -05:00
Julian Rosse
a35df430db AST: throw expected error messages (#5259)
* working through error messages

* import/export errors

* param assignability

* super

* non-top-level import TODO comment
2019-12-14 17:32:24 -05:00
Julian Rosse
05d45e9b27 astAsBlockIfNeeded(); eachName checkAssignability (#5258)
👍
2019-12-09 14:36:10 -08:00
Julian Rosse
69521b97ce AST: comment after semicolon (#5257)
* astNode()

* no override ast()

* add suggested comments

* astInitialize()

* astAddReturns()

* separate step

* recognize quoted constructor

* add params to scope

* object colon location data

* mark generated JSX tokens

* more generated tokens

* preserve comment after semicolon

* move comments

* Add explanation for token seeming mismatch
2019-12-08 16:18:00 -08:00
Julian Rosse
c7e538a624 AST: token cleanups (#5256)
* astNode()

* no override ast()

* add suggested comments

* astInitialize()

* astAddReturns()

* separate step

* recognize quoted constructor

* add params to scope

* object colon location data

* mark generated JSX tokens

* more generated tokens

* Add explanation for token seeming mismatch
2019-12-08 15:36:59 -08:00
Julian Rosse
44be72a4d9 AST: object colon location data (#5253)
* astNode()

* no override ast()

* add suggested comments

* astInitialize()

* astAddReturns()

* separate step

* recognize quoted constructor

* add params to scope

* object colon location data
2019-12-08 14:41:15 -08:00
Julian Rosse
9cfcf8623c AST: add params to scope (#5252)
* astNode()

* no override ast()

* add suggested comments

* astInitialize()

* astAddReturns()

* separate step

* recognize quoted constructor

* add params to scope
2019-12-08 14:41:02 -08:00
Julian Rosse
25c23786af AST: recognize quoted constructor (#5251)
* astNode()

* no override ast()

* add suggested comments

* astInitialize()

* astAddReturns()

* separate step

* recognize quoted constructor
2019-12-08 14:40:23 -08:00
Julian Rosse
47bf5d962b AST: mark implicit returns (#5255)
* astNode()

* no override ast()

* add suggested comments

* astInitialize()

* astAddReturns()

* separate step
2019-12-08 13:37:58 -08:00
Julian Rosse
a30e6807b1 add mark argument to makeReturn (#5254) 2019-12-06 14:54:30 -08:00
Julian Rosse
d735c81da0 Location data: compensate for stripped characters (#5249)
* location data compensations

* previous lines compensation
2019-12-01 12:26:10 -08:00
Julian Rosse
f56515b100 Compound assign location data (#5248)
* Assign declaration

* For

* Class

* import/export

* params

* Catch

* compound assign location data
2019-11-30 18:51:48 -08:00
Julian Rosse
74d6635f95 AST: declarations (#5247)
* Assign declaration

* For

* Class

* import/export

* params

* Catch
2019-11-30 18:49:10 -08:00
Julian Rosse
e8d0deae78 AST: expose tokens (#5246)
* respect withTokens option

* attach tokens to ast
2019-11-30 13:35:04 -08:00
Julian Rosse
95d6ec7492 handle empty program AST (#5245)
Looks good!
2019-11-28 16:31:10 -08:00
Robert de Forest
09c95394e1 Fix #5103: Add support for BigInt literals (#5104)
* Fix #5103: Add support for BigInt literals

* Fix typos found in testing

* Support binary, octal and hex BigInt literals

* Make decimal BigInt test consistent other bases

* Correct test BigInt test names

* Add Node versions to CI
2019-11-26 21:15:03 -08:00
Rich Trott
ddb5dac49d Add debugging information to error message test (#5239)
One of the test cases in test/error_messages.coffee fails intermittently
in the Node.js ecosystem-testing tool CITGM. In an effort to help debug
what's going on when this occurs, this adds more information to the
AssertionError message in question.
2019-10-18 11:03:16 -07:00
Julian Rosse
265b251a7d AST comments: include in blocks; heregex comments (#5233)
* simple trailing comment

* multiple trailing tests

* fix rebase

* leading comments

* empty block

* nested dedented comment

* check preceding

* trailing implicit call in condition

* don't include heregex comments in AST

* expose heregex comments in AST

* heregex comment location data

* don't use object spread
2019-08-24 01:10:08 -07:00
Julian Rosse
7539f7af2e Reconcile ast branch with Prettier plugin: part 2 (#5234)
* pass level

* assign always expression

* escaped backticks in PassthroughLiteral

* computed class properties
2019-08-18 17:30:24 -07:00
Julian Rosse
2f27225e8c JSX namespaced name AST (#5231)
* opening element

* closing element
2019-07-30 17:58:51 -07:00
Julian Rosse
99ad0cc16c Merge master into ast (#5230)
* Fix #5213: Update Babel options to restore MINIFY=false (#5214)

* CSX namespaced tags and attributes (#5218)

* Support namespaces in attributes

* Support namespaces in tag names

* Support reserved words in CSX boolean properties (fix #5125)

* Implement review comments

* Build

* Revert parser.js
2019-07-29 17:49:22 -07:00
Erik Demaine
70c2c4706f CSX namespaced tags and attributes (#5218)
* Support namespaces in attributes

* Support namespaces in tag names

* Support reserved words in CSX boolean properties (fix #5125)

* Implement review comments

* Build

* Revert parser.js
2019-07-29 14:54:57 -07:00
Julian Rosse
9d1af43c91 Start reconciling ast branch with Prettier plugin (#5228)
* export IDENTIFIER

* leading comment + directive

* function hasIndentedBody

* missing o

* Sequence

* root location data with leading comment

* empty interpolations

* fixes from code review
2019-07-29 09:07:10 -07:00
Julian Rosse
c6fdde8834 Chained comparison AST (#5225)
* chained comparison AST

* Explicit return

Co-Authored-By: Geoffrey Booth <GeoffreyBooth@users.noreply.github.com>
2019-07-24 07:11:42 -07:00
Julian Rosse
0174ee082c super AST (#5226) 2019-07-23 16:01:12 -07:00
Julian Rosse
82b7bd3a92 use OptionalMemberExpression/OptionalCallExpression (#5224) 2019-07-21 21:51:46 -07:00
Julian Rosse
1f22c16bee Basic comments AST; PassthroughLiteral AST (#5220)
* passing existing tests

* comments ast

* fixes from code review
2019-07-21 18:05:05 -07:00
Julian Rosse
f33d4dd4f1 Compile heredocs to template literals (#5211)
* compile heredocs to template literals

* disallow pseudo-octal escapes

* extend existing guard against continuations looking like octal escapes

* convert trailing null escapes

* nicer pattern for conditional heregex chunks

* remove covered test
2019-05-15 16:13:59 -07:00
Geoffrey Booth
9c913f86fa Fix #5213: Update Babel options to restore MINIFY=false (#5214) 2019-05-15 15:37:09 -07:00
Julian Rosse
f0bb59790a Directive AST (#5209)
* directive AST

* heredoc AST

* updates from code review
2019-05-05 21:07:04 -07:00
Julian Rosse
391fcc4afa Class AST: bound/computed properties, executable body (#5208)
* executable class body aST

* tests for bound/computed

* remove

* computed
2019-04-29 13:42:36 -07:00
Julian Rosse
7b2fb18a0b Class prototype property AST (#5205)
* class prototype property AST

* consistent naming

* extract fix for #5204
2019-04-28 16:54:59 -07:00
Geoffrey Booth
5596a5c209 Merge branch 'master' of github.com:jashkenas/coffeescript into ast
# Conflicts:
#	lib/coffeescript/grammar.js
#	lib/coffeescript/parser.js
2019-04-28 16:27:26 -07:00
Julian Rosse
71750554c3 Allow computed class properties (#5206)
* fix broken JS output

* static computed properties
2019-04-28 15:45:57 -07:00
Julian Rosse
0574b664e8 Fix #5201: allow leading breaking elision (#5202)
* allow simple breaking elision

* add tests

* use OptComma

* more tests

* trigger CI
2019-04-22 10:21:37 -07:00
Julian Rosse
ca0ac814b3 parse array ending in empty function (#5200) 2019-04-18 15:36:04 -07:00
Julian Rosse
c0b3217766 Class AST: static methods/properties (#5199)
@GeoffreyBooth PR for class static methods/static properties

Remaining parts of class ASTs include bound/computed methods/properties and executable class bodies
2019-04-15 10:06:00 -07:00
Julian Rosse
12a5271489 object property at LEVEL_LIST (#5197) 2019-04-09 23:19:04 -07:00
Geoffrey Booth
f4fcf65750 Don't publish .DS_Store to npm 2019-04-07 20:48:04 -07:00
Geoffrey Booth
92f69b2bca Release 2.4.1 (#5195)
* Fix #5133: Document that braces are required for object shorthand.

* Changelog for 2.4.1

* Update output
2019-04-07 20:41:37 -07:00
Geoffrey Booth
742224471f Actually publish the browser compilers to NPM (#5186)
* Actually publish the browser compilers to NPM

* Transpile and minify modern browser compiler; add to lib/ folder; update docs
2019-04-07 16:09:44 -07:00
Julian Rosse
086430840e basic class ast (#5194) 2019-04-05 21:31:25 -07:00
Julian Rosse
82f92fea97 allow indented property index (#5193) 2019-04-04 08:33:51 -07:00
Erik Demaine
d23919c430 Preserve environment when calling coffee from test (#5191)
This change spawns `coffee` with a new path, but without removing all other
environment variables.  This is useful for preserving environment needed by
Node, for example, `LD_LIBRARY_PATH` on Unix.  In particular, fix #5179.
2019-04-02 11:35:22 -07:00
Julian Rosse
ada35d8951 handle jsx element as expression (#5190) 2019-04-01 09:12:52 -07:00
Julian Rosse
7e0eb6a92d JSX empty expression location data (#5189) 2019-03-31 15:04:08 -07:00
Julian Rosse
28a1a1d304 AST: "CSX" -> "JSX" (#5188)
* updated grammar

* restore JSXIdentifier::astType()
2019-03-31 12:13:05 -07:00
Julian Rosse
0c2d3673d3 ast for jsx content (#5187) 2019-03-31 10:24:58 -07:00
Geoffrey Booth
e6f6aa8c85 Version bump in lockfile 2019-03-30 11:33:20 -07:00
Geoffrey Booth
c09d8fbedb Release 2.4.0 (#5182)
* cake doc:site:watch should also watch the changelog files

* Changelog for 2.4.0

* 2.4.0 output
2019-03-30 11:31:22 -07:00
Julian Rosse
730a4bcdad Tagged template literal AST (#5185)
* tagged template literal ast

* add comment
2019-03-30 11:31:00 -07:00
Julian Rosse
7466c81414 Index at LEVEL_PAREN (#5184) 2019-03-29 12:05:42 -07:00
Julian Rosse
b79ea321a3 regex ast (#5183) 2019-03-29 12:05:03 -07:00
Julian Rosse
ae2f72e15d Heregex AST (#5181)
* heregex ast

* fix from code review
2019-03-28 23:15:09 -07:00
Geoffrey Booth
f6d63776c3 ES module version of compiler for use in browsers; dynamic import() docs; revised Stage 3 policy (#5177)
* Build both a legacy and modern browser compiler

* Dynamic import example and documentation

* Update the docs to use the modern browser compiler if the browser supports it

* Update policy regarding Stage 3 features

* This never made sense, and assigning a string to index 0 *of a string* throws in Module mode (and silently does nothing in Script mode) so remove this unneeded code that throws when compiling `fn for i from from iterable` in Module mode

* Have browser-based tests use the ES module version if supported

* Simplify building logic

* Update output

* For the ES module version of the browser compiler, don't automatically attach the runScripts event handler

* Consistent comments

* Fix comment
2019-03-26 23:55:31 -07:00
Julian Rosse
b982b7cd0e dynamic import AST (#5180) 2019-03-26 08:20:12 -07:00
Geoffrey Booth
0b5bac666f Merge branch 'master' into ast
# Conflicts:
#	lib/coffeescript/grammar.js
#	lib/coffeescript/nodes.js
#	lib/coffeescript/parser.js
#	package-lock.json
#	src/nodes.coffee
#	test/error_messages.coffee
2019-03-24 19:22:33 -07:00
Ruben Bridgewater
41b31c7293 Fix repl.rli deprecation (#5178)
The `rli` property is just a reference to itself. It still exists
for legacy reasons but it will likely be removed in a future major
version. This makes sure everything works as expected.
2019-03-24 19:12:32 -07:00
Julian Rosse
eaeb77a527 String interpolation AST (#5175)
* updated grammar

* empty chunks

* remove unused

* remove unused

* add comment
2019-03-24 19:00:44 -07:00
Geoffrey Booth
ec034e2673 Fix tests (#5176)
* Fix cake test:integrations per newer Webpack

* Update dependencies

* Update dependencies
2019-03-23 23:28:13 -07:00
Julian Rosse
ff24e5ce52 Dynamic import (#5169)
* dynamic import

* updated grammar

* specify callable

* DynamicImportCall

* Fix from code review

Co-Authored-By: helixbass <julian@helixbass.net>

* recompile
2019-03-20 13:08:10 -07:00
Julian Rosse
4549f9a4c5 AST: Preserve infinity literal (#5172)
* updated grammar

* tests
2019-03-17 22:28:51 -07:00
Julian Rosse
d0be6391c6 For AST (#5173)
* updated grammar

* adding tests

* location data tests
2019-03-17 22:27:21 -07:00
Julian Rosse
f70f4f09b7 conditional else as simple expression (#5171) 2019-03-17 00:01:46 -07:00
Julian Rosse
3f5abb3c60 MetaProperty AST (new.target) (#5170)
* updated grammar

* updated grammar

* passing tests

* test errors ast
2019-03-16 18:51:39 -07:00
Julian Rosse
ca275c2a1c Fix #5128: parens around default param (#5167)
* compile params at LEVEL_PAREN

* test
2019-03-14 18:14:35 -07:00
Julian Rosse
99b7826f1b While AST (#5161)
* updated grammar

* tests

* add tests
2019-02-25 10:03:18 -08:00
Julian Rosse
806a442894 If AST (#5160)
* updated grammar

* updated grammar

* tests

* location data tests

* fix from code review
2019-02-14 19:51:33 -08:00
Alex
63ffe0aead Fix 5085 (#5145)
* Add test for #5085

    $ cake test
    failed 1 and passed 1274 tests in 4.81 seconds

      #5085: Bug: @ reference to class not maintained in do block
      AssertionError [ERR_ASSERTION]: Expected undefined to equal 2

* Fix #5085: @ reference to class in "do" block

Assuming that a bound Code node inside an ExecutableClassBody without a
name must be a "do" block.

* Additional tests

https://github.com/jashkenas/coffeescript/pull/5145#issuecomment-462127244

Also switched to concat'g strings for test values, as opposed to
incrementing numbers: makes the tests a bit easier to read.
2019-02-11 07:28:04 -08:00
Julian Rosse
74e0798f89 Return AST (#5157)
* updated grammar

* FuncDirectiveReturn class

* error tests
2019-02-10 08:48:48 -08:00
Robert de Forest
247b511c6a Remove extra word in comment in src/nodes.coffee (#5158) 2019-02-09 18:48:24 -08:00
Julian Rosse
6a8e6a4078 AST: Track exclusive end line/column (#5156)
* updated grammar (with patched Jison)

* passing tests

* updated grammar

* updated grammar

* updated grammar

* updated grammar

* cleanup

* refactor
2019-02-07 21:55:11 -08:00
Julian Rosse
42402da526 Code AST (#5155)
* adding tests

* updated grammar

* tests

* fixes from code review
2019-02-07 11:13:46 -08:00
Julian Rosse
42622b15a9 Switch AST (#5154)
* updated grammar

* ast

* fix merge

* tests

* location data tests

* fix from code review

* SwitchCase

* fix from code review
2019-02-02 13:28:06 -08:00
Julian Rosse
1879af6585 fixes (#5152)
Thank you for fixing this! This all looks great.
2019-01-22 11:32:51 -08:00
Julian Rosse
a7b1fa51e7 Try AST (#5140)
* root ast

* updated grammar

* preserve CoffeeScript.nodes() API

* root ast methods

* try ast

* updated grammar

* updated grammar

* updated grammar

* updated grammar

* finally location data

* remove unused

* updates from code review
2019-01-18 11:57:04 -08:00
Julian Rosse
38c8b2f35f Root AST (#5137)
* root ast

* updated grammar

* preserve CoffeeScript.nodes() API

* root ast methods

* updates from code review

* Style

* Fix a few missing returns

* Expand sourceType explanation

* Simplify

* Refactor Block.astProperties: use expression.astLocationData() to get location data, rather than extracting it from the whole AST object; move all the logic into one function, rather than spreading it out across several functions on the Block class that all appear to be internal

* testing root location data

* Fix location end data for root/File » Program AST node
2019-01-16 13:10:08 -08:00
Julian Rosse
4392d26985 JSX fragment/attribute AST (#5138)
* fragment ast

* attributes ast

* working on attribute classes

* passing tests
2018-11-30 11:30:50 -08:00
Adrian
2f82b75862 implement coffeescript.registerCompiled method (#5130)
* implement coffeescript._addSoucrse method

This method enables an external module to implement caching of
compilation results. When the compiled js source is loaded from cache,
the original coffee code should be added with this method in order to
enable the Error.prepareStackTrace below to correctly adjust the stack
trace for the corresponding file (the source map will be generated on
demand).

* replace _addSource with registerCompiled

* extract the logic from _compileFile into _compileRawFileContent

_compileFile takes care of logging the file and calls _compileRawFileContent

this way an external caching implementation which computes cache key
based on raw content of the sources file, can reuse the logic of
_compileFile and avoid having calling `fs.readFileSync` for the file
more twice in case of cache miss

* remove 'output' argument from registerCompiled
2018-11-28 09:09:06 -08:00
Julian Rosse
459814f58d JSX element AST (#5136)
* existence/throw/expansion ast

* updated grammar

* passing tests

* passing ast tests

* location data tests

* updates from code review

* add comment comments

* CSXElement

* jisonLocationDataToAstLocationData

* remove comment

* Style tweaks
2018-11-27 21:46:09 -08:00
Julian Rosse
088659f893 Existence/Throw/Expansion AST (#5135)
* existence/throw/expansion ast

* Style
2018-11-17 18:02:48 -08:00
Julian Rosse
0e37130f2e Assign AST (#5126)
* updated grammar

* tests

* ObjectProperty

* LHS shorthand with default needs @value

* remove unused Assign @shorthand

* assign ast

* test operator

* Format comment
2018-10-30 15:46:11 -07:00
Julian Rosse
fb539579c3 Object AST (#5124)
* updated grammar

* tests

* ObjectProperty

* LHS shorthand with default needs @value

* remove unused Assign @shorthand

* Format comments, cleanup style
2018-10-29 23:29:28 -07:00
Julian Rosse
7c54532010 Import/export AST (#5123)
* updated grammar

* tests

* Try to be a little clearer that we're assembling objects that we're returning

* explanatory comment
2018-10-22 09:53:11 -07:00
Julian Rosse
5d57ea785c array ast (#5120) 2018-10-15 21:17:45 -07:00
Julian Rosse
94e29c9a95 Range/Slice AST (#5119)
* op ast

* test expected errors

* use new ast methods

* remove unused abstraction

* logical ?

* fix rebase

* follow convention

* fixes from code review

* test helper naming

* always convert new to Call

* new cases

* don't mutate locationData

* updated grammar

* tests

* Rebuild

* always expose generated

* todo for OptionalMemberExpression

* range/slice ast

* Style tweaks
2018-10-15 10:00:14 -07:00
Julian Rosse
fe7377aed5 Call AST (#5117)
* op ast

* test expected errors

* use new ast methods

* remove unused abstraction

* logical ?

* fix rebase

* follow convention

* fixes from code review

* test helper naming

* always convert new to Call

* new cases

* don't mutate locationData

* updated grammar

* tests

* Rebuild

* always expose generated

* todo for OptionalMemberExpression
2018-10-14 19:07:12 -07:00
Julian Rosse
e934a42e75 Op AST (#5109)
* op ast

* test expected errors

* use new ast methods

* remove unused abstraction

* logical ?

* fix rebase

* follow convention

* fixes from code review

* test helper naming

* always convert new to Call

* new cases

* don't mutate locationData
2018-10-08 10:20:27 -07:00
Geoffrey Booth
294bb4754e Fix #5112: A string of ', ' in an array should not be detected as an elision (#5113) 2018-10-05 06:45:54 -07:00
Geoffrey Booth
5eab5f1d22 Merge pull request #5107 from helixbass/value-ast
Value AST
2018-10-01 09:16:38 -07:00
Julian Rosse
8b775c95ad Merge pull request #16 from GeoffreyBooth/value-ast-ast-methods
AST methods
2018-10-01 11:04:32 -04:00
Geoffrey Booth
251700549a Create helper to get the object for a Value AST node, including proper non-AST location data 2018-09-30 23:48:31 -07:00
Geoffrey Booth
3fbf76e135 Fix Parens 2018-09-30 23:16:00 -07:00
Geoffrey Booth
ca04dd6e47 Add helper for merging regular, non-AST location data 2018-09-30 22:55:55 -07:00
Geoffrey Booth
a82f869453 Add more comments, make consistent naming around Value overrides 2018-09-30 22:55:31 -07:00
Julian Rosse
f932206213 super() when properties 2018-09-26 10:49:28 -04:00
Geoffrey Booth
849dd53287 Formatting 2018-09-25 21:37:35 -07:00
Geoffrey Booth
e03a87da04 Improve comments 2018-09-25 21:22:52 -07:00
Geoffrey Booth
29aa9b36fe Refactor AST methods 2018-09-25 21:13:21 -07:00
Julian Rosse
c6472fa617 Merge pull request #15 from GeoffreyBooth/value-ast-revisions-helpers
AST helpers revisions
2018-09-25 22:04:54 -04:00
Julian Rosse
1bbbca6496 comment 2018-09-25 22:03:40 -04:00
Geoffrey Booth
6b1e9bb82b Refactor to use new mergeAstLocationData 2018-09-24 23:43:24 -07:00
Geoffrey Booth
eb22196850 Globalize helpers 2018-09-24 23:32:21 -07:00
Geoffrey Booth
3b1c49240b Fix inspect helper 2018-09-24 23:32:20 -07:00
Geoffrey Booth
ea33c28f1b Refactor our helper for merging AST location data to take two locationData objects and return a new, merged one 2018-09-24 22:00:10 -07:00
Geoffrey Booth
7b251f493d Make error message for location AST paths connect the path to the property we're comparing 2018-09-24 22:00:05 -07:00
Geoffrey Booth
0be8c5d161 Make AST test output browser-safe; improve output for failing tests; have output follow style of eqJS 2018-09-24 21:59:59 -07:00
Geoffrey Booth
617a2d5b65 Don't change style of functions defined with sequential arguments vs options argument; keep the focus of this PR on the AST work, not on unnecessary style changes 2018-09-24 21:59:53 -07:00
Geoffrey Booth
e1625a0d31 We don't need to abstract a new helpers file for just three lines of code, there's more code required to pull this in where it's needed than to just duplicate the two lines of code we need in both places where these 'shared' helpers are currently used 2018-09-24 21:59:44 -07:00
Geoffrey Booth
4c6cc8d060 Merge branch 'ast' of github.com:jashkenas/coffeescript into value-ast
# Conflicts:
#	lib/coffeescript/parser.js
2018-09-20 00:20:30 -07:00
Geoffrey Booth
e6153d9841 Merge branch 'master' of github.com:jashkenas/coffeescript into ast
# Conflicts:
#	lib/coffeescript/parser.js
2018-09-20 00:17:53 -07:00
Julian Rosse
d83b95bd39 updated Cakefile 2018-09-17 15:04:04 -04:00
Julian Rosse
4ba1be131c test nested location data 2018-09-17 15:04:04 -04:00
Julian Rosse
8dabec0f9b use Object.assign 2018-09-17 15:04:04 -04:00
Julian Rosse
e679cbccf7 default to forceUpdateLocation 2018-09-17 15:04:04 -04:00
Julian Rosse
b18e91f936 use new ast methods 2018-09-17 15:04:04 -04:00
Julian Rosse
c31a30d3fa test parens 2018-09-17 15:04:04 -04:00
Julian Rosse
99b2578aa7 force update location data in grammar 2018-09-17 15:04:04 -04:00
Julian Rosse
ddfde6810c updated access grammar 2018-09-17 15:04:04 -04:00
Julian Rosse
71350d67c4 AST generation hooks (#5099)
* include range in location data

* use exclusive ranges

* ast generation hooks

* fix getAstChildren()

* babylon -

* isArray -> Array.isArray

* pass options to toJSON()

* default astType on Base

* using exclusive range

* extract location data tests

* babylon -> ast

* remove do ->

* _toAst -> getAstContent

* Pass through parsed number value from lexer to node; don't process more than is necessary (a number literal can never be negative, because the negative sign is an Op token and node)

* normalize NumberLiteral values

* use parsedValue in getNumberValue()

* recursive getNumberValue()

* parseNumber()

* The core JavaScript Number constructor does a better job at parsing strings into numbers than our helper does

* Use Object.assign rather than merge or extend

* Update link

* Cleanup style

* Refactor to make AST generation more object-oriented: have each of the AST properties be generated on the node itself, rather than in loops in the base class

* Untangle test helpers: give the AST location tests their own specific helper function, and move the general AST helper functions into the main AST tests file

* Not passing o

* Add node type check to AST location data tests
2018-09-17 10:40:37 -07:00
Geoffrey Booth
13857a5d71 Merge branch 'master' into ast
# Conflicts:
#	Cakefile
#	package-lock.json
#	package.json
2018-09-16 14:00:45 -07:00
Julian Rosse
6ce1d36acd use exclusive ranges 2018-09-09 00:31:59 -07:00
Julian Rosse
b2669abecc include range in location data 2018-09-09 00:31:59 -07:00
Geoffrey Booth
db86dc4d8b AST tests (#5097)
* fix momentum scrolling on iOS (#5083)

* Revert "fix momentum scrolling on iOS (#5083)" (#5084)

This reverts commit 812571843c.

* AST tests (WIP)

* added tests

* cleanup

new helpers for cleaner code

* more tests

tests are mostly complete now.
also included one for our helper function.

* string quotes

* Update dependencies; disable some babel-minify transforms to work around https://github.com/babel/minify/issues/893 (#5095)

* more tests + refactor

* Remove unused helper function; improve logging output

* Add tests for ImportNamespaceSpecifier, Expansion; cleanup

* CI: Test first before building, so that the tests run on the committed, built files in /lib; the build parts of CI are only a test that the build process succeeds, so we shouldn't be testing the output of the CI build steps
2018-08-18 15:45:31 -07:00
Julian Rosse
16b4448fe8 Chained do IIFE: use grammar, not rewriter (#5070)
* grammar rules for DO/DO_IIFE

* remove rewriter pass
2018-07-11 22:37:05 -07:00
Julian Rosse
af82c1f41f Preserve aliased operators (#5059)
* pass quote through grammar

* pass through initialChunk/finalChunk

* passing tests

* always unwrap string object

* fixes from code review

* preserve passthrough literals

* cleaner approach

* preserve aliased operators

* normalize

* include guard against preserve-string-literal

* store boolean originalValue

* preserve not in

* invert in

* defer inverting in

* preserve or=

* only wrap when data

* use addTokenData(), unwrap in grammar

* shift more string formatting into nodes

* RegexWithInterpolations wrap Call

* preserve heregexen

* alias guard for imports

* preserve invert operator

* revert Cakefile

* fixes from code review

* isInOperator()
2018-06-19 16:31:46 -07:00
Julian Rosse
3e089ca59d Preserve empty interpolations (#5079)
* pass quote through grammar

* pass through initialChunk/finalChunk

* passing tests

* always unwrap string object

* fixes from code review

* preserve passthrough literals

* cleaner approach

* only wrap when data

* shift more string formatting into nodes

* RegexWithInterpolations wrap Call

* preserve heregexen

* fixes per code review

* fix merge

* fix from code review

* fixes from code review

* passing tests

* fixes from code review

* just define in nodes

* fix from code review

* add comment for toPrimitiveString()

* fix from code review
2018-06-17 15:36:26 -07:00
Geoffrey Booth
8a25195442 AST flag/API option; generic AST output for all nodes (#5044)
* Add `nodes` option to Node API, that returns POJO representation of AST; starting point for toPlainObject method on node classes to return the serializable plain JavaScript object representation of each node

* Make --nodes also return JSON (pretty-printed, though not colorized)

* Alphabetize CLI flags

* Use new `ast` flag to request AST, restoring prior `nodes` flag; rename toPlainObject to toJSON
2018-06-11 19:50:40 -07:00
136 changed files with 58788 additions and 15068 deletions

View File

@@ -0,0 +1,44 @@
# Based on https://github.com/actions/starter-workflows/blob/master/ci/node.js.yml
name: Build and Test
on: [push, pull_request]
jobs:
ci:
runs-on: ${{ matrix.operating-system }}
strategy:
matrix:
operating-system: [ubuntu-latest, macos-latest, windows-latest]
node-version: [12.x, 14.x, 16.x, 17.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
# Ensure that we can still build in the current version of Node
- run: node ./bin/cake build:except-parser
- run: node ./bin/cake build:parser
# Build twice to ensure that the latest build of the compiler can still build itself
- run: node ./bin/cake build:except-parser
- run: node ./bin/cake build:parser
# Build the browser compiler for the headless browser test
- run: node ./bin/cake build:browser
# Build test.html, so that test:browser uses the latest tests
- run: node ./bin/cake doc:test
# Check that the git diff is clean, to ensure that the updated build output was committed
- run: git diff --exit-code
# Test
- run: node ./bin/cake test
- run: node ./bin/cake test:browser
- run: node ./bin/cake test:browser:node
- run: node ./bin/cake test:integrations

1
.gitignore vendored
View File

@@ -9,3 +9,4 @@ parser.output
/node_modules
npm-debug.log*
yarn.lock
.DS_Store

View File

@@ -1,20 +0,0 @@
language: node_js
node_js:
- 6
- 8
- 10
cache:
directories:
- node_modules
script:
- node ./bin/cake build:except-parser
- node ./bin/cake build:parser
- node ./bin/cake build:full
- node ./bin/cake build:browser
- node ./bin/cake test
- node --harmony ./bin/cake test
- node ./bin/cake test:browser
- node ./bin/cake test:integrations

145
Cakefile
View File

@@ -21,7 +21,7 @@ header = """
* CoffeeScript Compiler v#{CoffeeScript.VERSION}
* https://coffeescript.org
*
* Copyright 2011, Jeremy Ashkenas
* Copyright 2011-#{new Date().getFullYear()}, Jeremy Ashkenas
* Released under the MIT License
*/
"""
@@ -66,18 +66,23 @@ build = (callback) ->
buildParser()
buildExceptParser callback
transpile = (code) ->
transpile = (code, options = {}) ->
options.minify = process.env.MINIFY isnt 'false'
options.transform = process.env.TRANSFORM isnt 'false'
options.sourceType ?= 'script'
babel = require '@babel/core'
presets = []
# Exclude the `modules` plugin in order to not break the `}(this));`
# at the end of the `build:browser` code block.
presets.push ['@babel/env', {modules: no}] unless process.env.TRANSFORM is 'false'
presets.push ['minify', {mangle: no, evaluate: no, removeUndefined: no}] unless process.env.MINIFY is 'false'
presets.push ['@babel/env', {modules: no}] if options.transform
presets.push ['minify', {mangle: no, evaluate: no, removeUndefined: no}] if options.minify
babelOptions =
compact: process.env.MINIFY isnt 'false'
presets: presets
sourceType: 'script'
{ code } = babel.transform code, babelOptions unless presets.length is 0
compact: options.minify
minified: options.minify
comments: not options.minify
sourceType: options.sourceType
{ code } = babel.transformSync code, babelOptions unless presets.length is 0
code
testBuiltCode = (watch = no) ->
@@ -140,13 +145,18 @@ task 'build:browser', 'merge the built scripts into a single file for use in a b
return module.exports;
})();
"""
# From here, we generate two outputs: a legacy script output for all browsers
# and a module output for browsers that support `<script type="module">`.
code = """
var CoffeeScript = function() {
function require(path){ return require[path]; }
#{code}
return require['./browser'];
}();
"""
scriptCode = transpile """
(function(root) {
var CoffeeScript = function() {
function require(path){ return require[path]; }
#{code}
return require['./browser'];
}();
#{code}
if (typeof define === 'function' && define.amd) {
define(function() { return CoffeeScript; });
@@ -155,10 +165,25 @@ task 'build:browser', 'merge the built scripts into a single file for use in a b
}
}(this));
"""
code = transpile code
outputFolder = "docs/v#{majorVersion}/browser-compiler"
fs.mkdirSync outputFolder unless fs.existsSync outputFolder
fs.writeFileSync "#{outputFolder}/coffeescript.js", header + '\n' + code
moduleCode = transpile """
#{code}
export default CoffeeScript;
const { VERSION, compile, eval: evaluate, load, run, runScripts } = CoffeeScript;
export { VERSION, compile, evaluate as eval, load, run, runScripts };
""", {sourceType: 'module'}
outputFolders = [
"docs/v#{majorVersion}/browser-compiler-legacy"
"docs/v#{majorVersion}/browser-compiler-modern"
"lib/coffeescript-browser-compiler-legacy"
"lib/coffeescript-browser-compiler-modern"
]
for outputFolder in outputFolders
fs.mkdirSync outputFolder unless fs.existsSync outputFolder
fs.writeFileSync "#{outputFolder}/coffeescript.js", """
#{header}
#{if outputFolder.includes('legacy') then scriptCode else moduleCode}
"""
task 'build:browser:full', 'merge the built scripts into a single file for use in a browser, and test it', ->
invoke 'build:browser'
@@ -174,11 +199,12 @@ task 'build:watch:harmony', 'watch and continually rebuild the CoffeeScript comp
buildDocs = (watch = no) ->
# Constants
indexFile = 'documentation/site/index.html'
siteSourceFolder = "documentation/site"
sectionsSourceFolder = 'documentation/sections'
examplesSourceFolder = 'documentation/examples'
outputFolder = "docs/v#{majorVersion}"
indexFile = 'documentation/site/index.html'
siteSourceFolder = "documentation/site"
sectionsSourceFolder = 'documentation/sections'
changelogSourceFolder = 'documentation/sections/changelog'
examplesSourceFolder = 'documentation/examples'
outputFolder = "docs/v#{majorVersion}"
# Helpers
releaseHeader = (date, version, prevVersion) ->
@@ -196,11 +222,11 @@ buildDocs = (watch = no) ->
markdownRenderer = require('markdown-it')
html: yes
typographer: yes
highlight: (str, lang) ->
highlight: (str, language) ->
# From https://github.com/markdown-it/markdown-it#syntax-highlighting
if lang and hljs.getLanguage(lang)
if language and hljs.getLanguage(language)
try
return hljs.highlight(lang, str).value
return hljs.highlight(str, { language }).value
catch ex
return '' # No syntax highlighting
@@ -261,7 +287,7 @@ buildDocs = (watch = no) ->
catch exception
if watch
for target in [indexFile, siteSourceFolder, examplesSourceFolder, sectionsSourceFolder]
for target in [indexFile, siteSourceFolder, examplesSourceFolder, sectionsSourceFolder, changelogSourceFolder]
fs.watch target, interval: 200, renderIndex
log 'watching...', green
@@ -284,7 +310,7 @@ buildDocTests = (watch = no) ->
# Helpers
testsInScriptBlocks = ->
output = ''
for filename in fs.readdirSync testsSourceFolder
for filename in fs.readdirSync(testsSourceFolder).sort()
if filename.indexOf('.coffee') isnt -1
type = 'coffeescript'
else if filename.indexOf('.litcoffee') isnt -1
@@ -342,11 +368,13 @@ task 'release', 'build and test the CoffeeScript source, and build the documenta
execSync '''
cake build:full
cake build:browser
cake doc:test
cake test:browser:node
cake test:browser
cake test:integrations
cake doc:site
cake doc:test
cake doc:source''', stdio: 'inherit'
cake doc:source
''', stdio: 'inherit'
task 'bench', 'quick benchmark of compilation time', ->
@@ -446,6 +474,9 @@ runTests = (CoffeeScript) ->
skipUnless 'var a = 2 ** 2; a **= 3', ['exponentiation.coffee']
skipUnless 'var {...a} = {}', ['object_rest_spread.coffee']
skipUnless '/foo.bar/s.test("foo\tbar")', ['regex_dotall.coffee']
skipUnless '1_2_3', ['numeric_literal_separators.coffee']
skipUnless '1n', ['numbers_bigint.coffee']
skipUnless 'async () => { await import(\'data:application/json,{"foo":"bar"}\', { assert: { type: "json" } }) }', ['import_assertions.coffee']
files = fs.readdirSync('test').filter (filename) ->
filename not in testFilesToSkip
@@ -467,8 +498,54 @@ task 'test', 'run the CoffeeScript language test suite', ->
runTests(CoffeeScript).catch -> process.exit 1
task 'test:browser', 'run the test suite against the merged browser script', ->
source = fs.readFileSync "docs/v#{majorVersion}/browser-compiler/coffeescript.js", 'utf-8'
task 'test:browser', 'run the test suite against the modern browser compiler in a headless browser', ->
# Create very simple web server to serve the two files we need.
http = require 'http'
serveFile = (res, fileToServe, mimeType) ->
res.statusCode = 200
res.setHeader 'Content-Type', mimeType
fs.createReadStream(fileToServe).pipe res
server = http.createServer (req, res) ->
if req.url is '/'
serveFile res, path.join(__dirname, 'docs', "v#{majorVersion}", 'test.html'), 'text/html'
else if req.url is '/browser-compiler-modern/coffeescript.js'
# The `text/javascript` MIME type is required for an ES module file to be
# loaded in a browser.
serveFile res, path.join(__dirname, 'docs', "v#{majorVersion}", 'browser-compiler-modern', 'coffeescript.js'), 'text/javascript'
else
res.statusCode = 404
res.end()
server.listen 8080, ->
puppeteer = require 'puppeteer'
browser = await puppeteer.launch()
page = await browser.newPage()
result = ""
try
await page.goto 'http://localhost:8080/'
element = await page.waitForSelector '#result',
visible: yes
polling: 'mutation'
timeout: 60000
result = await page.evaluate ((el) => el.textContent), element
catch e
log e, red
finally
try browser.close()
server.close()
if result and not result.includes('failed')
log result, green
else
log result, red
process.exit 1
task 'test:browser:node', 'run the test suite against the legacy browser compiler in Node', ->
source = fs.readFileSync "lib/coffeescript-browser-compiler-legacy/coffeescript.js", 'utf-8'
result = {}
global.testingBrowser = yes
(-> eval source).call result
@@ -482,10 +559,16 @@ task 'test:integrations', 'test the module integrated with other libraries and e
# can be built by such tools; if such a build succeeds, it verifies that no
# 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.
# Webpack 5 requires Node >= 10.13.0.
[major, minor] = process.versions.node.split('.').map (n) -> parseInt(n, 10)
return if major < 10 or (major is 10 and minor < 13)
tmpdir = os.tmpdir()
webpack = require 'webpack'
webpack {
entry: './'
optimization:
# Webpacks minification causes the CoffeeScript module to fail some tests.
minimize: off
output:
path: tmpdir
filename: 'coffeescript.js'
@@ -503,7 +586,7 @@ task 'test:integrations', 'test the module integrated with other libraries and e
process.exit 1
builtCompiler = path.join tmpdir, 'coffeescript.js'
CoffeeScript = require builtCompiler
{ CoffeeScript } = require builtCompiler
global.testingBrowser = yes
testResults = runTests CoffeeScript
fs.unlinkSync builtCompiler

View File

@@ -1,29 +0,0 @@
environment:
matrix:
- nodejs_version: '6'
- nodejs_version: '8'
- nodejs_version: '10'
- nodejs_version: '' # Installs latest.
install:
- ps: Install-Product node $env:nodejs_version
- node --version
- npm --version
- npm install
cache:
- node_modules
test_script:
- node ./bin/cake build:except-parser
- node ./bin/cake build:parser
- node ./bin/cake build:full
- node ./bin/cake build:browser
- node ./bin/cake test
- node --harmony ./bin/cake test
- node ./bin/cake test:browser
- node ./bin/cake test:integrations
build: off
version: "{build}"

View File

@@ -1 +1 @@
v2/browser-compiler
v2/browser-compiler-legacy

View File

@@ -0,0 +1 @@
v2/browser-compiler-legacy

View File

@@ -0,0 +1 @@
v2/browser-compiler-modern

View File

@@ -555,7 +555,8 @@ pre .xml .cdata {
<a href="#destructuring">Destructuring Assignment</a>
<a href="#fat-arrow">Bound and Generator Functions</a>
<a href="#embedded">Embedded JavaScript</a>
<a href="#switch">Switch and Try/Catch</a>
<a href="#switch">Switch/When/Else</a>
<a href="#try-catch">Try/Catch/Finally</a>
<a href="#comparisons">Chained Comparisons</a>
<a href="#strings">String Interpolation, Block Strings, and Block Comments</a>
<a href="#tagged-template-literals">Tagged Template Literals</a>
@@ -853,7 +854,7 @@ cubes = (function() {
<h2>Language Reference</h2>
<p><em>This reference is structured so that it can be read from top to bottom, if you like. Later sections use ideas and syntax previously introduced. Familiarity with JavaScript is assumed. In all of the following examples, the source CoffeeScript is provided on the left, and the direct compilation into JavaScript is on the right.</em></p>
<p><em>Many of the examples can be run (where it makes sense) by pressing the <strong>run</strong> button on the right, and can be loaded into the “Try CoffeeScript” console by pressing the <strong>load</strong> button on the left.</em></p>
<p>First, the basics: CoffeeScript uses significant whitespace to delimit blocks of code. You dont need to use semicolons <code>;</code> to terminate expressions, ending the line will do just as well (although semicolons can still be used to fit multiple expressions onto a single line). Instead of using curly braces <code>{ }</code> to surround blocks of code in <a href="#literals">functions</a>, <a href="#conditionals">if-statements</a>, <a href="#switch">switch</a>, and <a href="#try">try/catch</a>, use indentation.</p>
<p>First, the basics: CoffeeScript uses significant whitespace to delimit blocks of code. You dont need to use semicolons <code>;</code> to terminate expressions, ending the line will do just as well (although semicolons can still be used to fit multiple expressions onto a single line). Instead of using curly braces <code>{ }</code> to surround blocks of code in <a href="#literals">functions</a>, <a href="#conditionals">if-statements</a>, <a href="#switch">switch</a>, and <a href="#try-catch">try/catch</a>, use indentation.</p>
<p>You dont need to use parentheses to invoke a function if youre passing arguments. The implicit call wraps forward to the end of the line or block expression.<br>
<code>console.log sys.inspect object</code><code>console.log(sys.inspect(object));</code></p>

View File

@@ -112,8 +112,8 @@
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-1">&#x00a7;</a>
</div>
<p>This <strong>Browser</strong> compatibility layer extends core CoffeeScript functions
to make things work smoothly when compiling code directly in the browser.
@@ -123,7 +123,7 @@ We add support for loading remote Coffee scripts via <strong>XHR</strong>, and
</div>
<div class="content"><div class='highlight'><pre>
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./coffeescript'</span>
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./coffeescript&#x27;</span>
{ compile } = CoffeeScript</pre></div></div>
</li>
@@ -132,8 +132,8 @@ CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-stri
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-2">&#x00a7;</a>
</div>
<p>Use <code>window.eval</code> to evaluate code, rather than just <code>eval</code>, to run the
script in a clean global scope rather than inheriting the scope of the
@@ -142,10 +142,10 @@ use either <code>window.eval</code> or <code>global.eval</code> as appropriate).
</div>
<div class="content"><div class='highlight'><pre>CoffeeScript.eval = <span class="hljs-function"><span class="hljs-params">(code, options = {})</span> -&gt;</span>
<div class="content"><div class='highlight'><pre>CoffeeScript.<span class="hljs-built_in">eval</span> = <span class="hljs-function"><span class="hljs-params">(code, options = {})</span> -&gt;</span>
options.bare ?= <span class="hljs-literal">on</span>
globalRoot = <span class="hljs-keyword">if</span> <span class="hljs-built_in">window</span>? <span class="hljs-keyword">then</span> <span class="hljs-built_in">window</span> <span class="hljs-keyword">else</span> <span class="hljs-built_in">global</span>
globalRoot[<span class="hljs-string">'eval'</span>] compile code, options</pre></div></div>
globalRoot = <span class="hljs-keyword">if</span> window? <span class="hljs-keyword">then</span> window <span class="hljs-keyword">else</span> global
globalRoot[<span class="hljs-string">&#x27;eval&#x27;</span>] compile code, options</pre></div></div>
</li>
@@ -153,8 +153,8 @@ use either <code>window.eval</code> or <code>global.eval</code> as appropriate).
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-3">&#x00a7;</a>
</div>
<p>Running code does not provide access to this scope.</p>
@@ -163,7 +163,7 @@ use either <code>window.eval</code> or <code>global.eval</code> as appropriate).
<div class="content"><div class='highlight'><pre>CoffeeScript.run = <span class="hljs-function"><span class="hljs-params">(code, options = {})</span> -&gt;</span>
options.bare = <span class="hljs-literal">on</span>
options.shiftLine = <span class="hljs-literal">on</span>
Function(compile code, options)()</pre></div></div>
<span class="hljs-built_in">Function</span>(compile code, options)()</pre></div></div>
</li>
@@ -171,15 +171,15 @@ use either <code>window.eval</code> or <code>global.eval</code> as appropriate).
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-4">&#x00a7;</a>
</div>
<p>Export this more limited <code>CoffeeScript</code> than what is exported by
<code>index.coffee</code>, which is intended for a Node environment.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">module</span>.exports = CoffeeScript</pre></div></div>
<div class="content"><div class='highlight'><pre>module.<span class="hljs-built_in">exports</span> = CoffeeScript</pre></div></div>
</li>
@@ -187,14 +187,14 @@ use either <code>window.eval</code> or <code>global.eval</code> as appropriate).
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-5">&#x00a7;</a>
</div>
<p>If were not in a browser environment, were finished with the public API.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> <span class="hljs-built_in">window</span>?</pre></div></div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> window?</pre></div></div>
</li>
@@ -202,8 +202,8 @@ use either <code>window.eval</code> or <code>global.eval</code> as appropriate).
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-6">&#x00a7;</a>
</div>
<p>Include source maps where possible. If weve got a base64 encoder, a
JSON serializer, and tools for escaping unicode characters, were good to go.
@@ -211,7 +211,7 @@ Ported from <a href="https://developer.mozilla.org/en-US/docs/DOM/window.btoa">h
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> btoa? <span class="hljs-keyword">and</span> JSON?
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> btoa? <span class="hljs-keyword">and</span> <span class="hljs-built_in">JSON</span>?
<span class="hljs-function"> <span class="hljs-title">compile</span> = <span class="hljs-params">(code, options = {})</span> -&gt;</span>
options.inlineMap = <span class="hljs-literal">true</span>
CoffeeScript.compile code, options</pre></div></div>
@@ -222,8 +222,8 @@ Ported from <a href="https://developer.mozilla.org/en-US/docs/DOM/window.btoa">h
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-7">&#x00a7;</a>
</div>
<p>Load a remote script from the current domain via XHR.</p>
@@ -231,19 +231,19 @@ Ported from <a href="https://developer.mozilla.org/en-US/docs/DOM/window.btoa">h
<div class="content"><div class='highlight'><pre>CoffeeScript.load = <span class="hljs-function"><span class="hljs-params">(url, callback, options = {}, hold = <span class="hljs-literal">false</span>)</span> -&gt;</span>
options.sourceFiles = [url]
xhr = <span class="hljs-keyword">if</span> <span class="hljs-built_in">window</span>.ActiveXObject
<span class="hljs-keyword">new</span> <span class="hljs-built_in">window</span>.ActiveXObject(<span class="hljs-string">'Microsoft.XMLHTTP'</span>)
xhr = <span class="hljs-keyword">if</span> window.ActiveXObject
<span class="hljs-keyword">new</span> window.ActiveXObject(<span class="hljs-string">&#x27;Microsoft.XMLHTTP&#x27;</span>)
<span class="hljs-keyword">else</span>
<span class="hljs-keyword">new</span> <span class="hljs-built_in">window</span>.XMLHttpRequest()
xhr.open <span class="hljs-string">'GET'</span>, url, <span class="hljs-literal">true</span>
xhr.overrideMimeType <span class="hljs-string">'text/plain'</span> <span class="hljs-keyword">if</span> <span class="hljs-string">'overrideMimeType'</span> <span class="hljs-keyword">of</span> xhr
<span class="hljs-keyword">new</span> window.XMLHttpRequest()
xhr.open <span class="hljs-string">&#x27;GET&#x27;</span>, url, <span class="hljs-literal">true</span>
xhr.overrideMimeType <span class="hljs-string">&#x27;text/plain&#x27;</span> <span class="hljs-keyword">if</span> <span class="hljs-string">&#x27;overrideMimeType&#x27;</span> <span class="hljs-keyword">of</span> xhr
xhr.onreadystatechange = <span class="hljs-function">-&gt;</span>
<span class="hljs-keyword">if</span> xhr.readyState <span class="hljs-keyword">is</span> <span class="hljs-number">4</span>
<span class="hljs-keyword">if</span> xhr.status <span class="hljs-keyword">in</span> [<span class="hljs-number">0</span>, <span class="hljs-number">200</span>]
param = [xhr.responseText, options]
CoffeeScript.run param... <span class="hljs-keyword">unless</span> hold
<span class="hljs-keyword">else</span>
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"Could not load <span class="hljs-subst">#{url}</span>"</span>
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">&quot;Could not load <span class="hljs-subst">#{url}</span>&quot;</span>
callback param <span class="hljs-keyword">if</span> callback
xhr.send <span class="hljs-literal">null</span></pre></div></div>
@@ -253,8 +253,8 @@ Ported from <a href="https://developer.mozilla.org/en-US/docs/DOM/window.btoa">h
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-8">&#x00a7;</a>
</div>
<p>Activate CoffeeScript in the browser by having it compile and evaluate
all script tags with a content-type of <code>text/coffeescript</code>.
@@ -262,15 +262,15 @@ This happens on page load.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">runScripts</span> = -&gt;</span>
scripts = <span class="hljs-built_in">window</span>.<span class="hljs-built_in">document</span>.getElementsByTagName <span class="hljs-string">'script'</span>
coffeetypes = [<span class="hljs-string">'text/coffeescript'</span>, <span class="hljs-string">'text/literate-coffeescript'</span>]
<div class="content"><div class='highlight'><pre>CoffeeScript.runScripts = <span class="hljs-function">-&gt;</span>
scripts = window.document.getElementsByTagName <span class="hljs-string">&#x27;script&#x27;</span>
coffeetypes = [<span class="hljs-string">&#x27;text/coffeescript&#x27;</span>, <span class="hljs-string">&#x27;text/literate-coffeescript&#x27;</span>]
coffees = (s <span class="hljs-keyword">for</span> s <span class="hljs-keyword">in</span> scripts <span class="hljs-keyword">when</span> s.type <span class="hljs-keyword">in</span> coffeetypes)
index = <span class="hljs-number">0</span>
<span class="hljs-function">
<span class="hljs-title">execute</span> = -&gt;</span>
param = coffees[index]
<span class="hljs-keyword">if</span> param <span class="hljs-keyword">instanceof</span> Array
<span class="hljs-keyword">if</span> param <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>
CoffeeScript.run param...
index++
execute()
@@ -278,7 +278,7 @@ This happens on page load.</p>
<span class="hljs-keyword">for</span> script, i <span class="hljs-keyword">in</span> coffees
<span class="hljs-keyword">do</span> (script, i) -&gt;
options = literate: script.type <span class="hljs-keyword">is</span> coffeetypes[<span class="hljs-number">1</span>]
source = script.src <span class="hljs-keyword">or</span> script.getAttribute(<span class="hljs-string">'data-src'</span>)
source = script.src <span class="hljs-keyword">or</span> script.getAttribute(<span class="hljs-string">&#x27;data-src&#x27;</span>)
<span class="hljs-keyword">if</span> source
options.filename = source
CoffeeScript.load source,
@@ -295,8 +295,8 @@ This happens on page load.</p>
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-9">&#x00a7;</a>
</div>
<p><code>options.filename</code> defines the filename the source map appears as
in Developer Tools. If a script tag has an <code>id</code>, use that as the
@@ -306,8 +306,8 @@ only one CoffeeScript script block to parse.</p>
</div>
<div class="content"><div class='highlight'><pre> options.filename = <span class="hljs-keyword">if</span> script.id <span class="hljs-keyword">and</span> script.id <span class="hljs-keyword">isnt</span> <span class="hljs-string">''</span> <span class="hljs-keyword">then</span> script.id <span class="hljs-keyword">else</span> <span class="hljs-string">"coffeescript<span class="hljs-subst">#{<span class="hljs-keyword">if</span> i <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> i <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>}</span>"</span>
options.sourceFiles = [<span class="hljs-string">'embedded'</span>]
<div class="content"><div class='highlight'><pre> options.filename = <span class="hljs-keyword">if</span> script.id <span class="hljs-keyword">and</span> script.id <span class="hljs-keyword">isnt</span> <span class="hljs-string">&#x27;&#x27;</span> <span class="hljs-keyword">then</span> script.id <span class="hljs-keyword">else</span> <span class="hljs-string">&quot;coffeescript<span class="hljs-subst">#{<span class="hljs-keyword">if</span> i <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> i <span class="hljs-keyword">else</span> <span class="hljs-string">&#x27;&#x27;</span>}</span>&quot;</span>
options.sourceFiles = [<span class="hljs-string">&#x27;embedded&#x27;</span>]
coffees[i] = [script.innerHTML, options]
execute()</pre></div></div>
@@ -318,17 +318,22 @@ only one CoffeeScript script block to parse.</p>
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-10">&#x00a7;</a>
</div>
<p>Listen for window load, both in decent browsers and in IE.</p>
<p>Listen for window load, both in decent browsers and in IE.
Only attach this event handler on startup for the
non-ES module version of the browser compiler, to preserve
backward compatibility while letting the ES module version
be importable without side effects.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> <span class="hljs-built_in">window</span>.addEventListener
<span class="hljs-built_in">window</span>.addEventListener <span class="hljs-string">'DOMContentLoaded'</span>, runScripts, <span class="hljs-literal">no</span>
<span class="hljs-keyword">else</span>
<span class="hljs-built_in">window</span>.attachEvent <span class="hljs-string">'onload'</span>, runScripts</pre></div></div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> this <span class="hljs-keyword">is</span> window
<span class="hljs-keyword">if</span> window.addEventListener
window.addEventListener <span class="hljs-string">&#x27;DOMContentLoaded&#x27;</span>, CoffeeScript.runScripts, <span class="hljs-literal">no</span>
<span class="hljs-keyword">else</span>
window.attachEvent <span class="hljs-string">&#x27;onload&#x27;</span>, CoffeeScript.runScripts</pre></div></div>
</li>

View File

@@ -112,8 +112,8 @@
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-1">&#x00a7;</a>
</div>
<p><code>cake</code> is a simplified version of <a href="http://www.gnu.org/software/make/">Make</a>
(<a href="http://rake.rubyforge.org/">Rake</a>, <a href="https://github.com/280north/jake">Jake</a>)
@@ -130,18 +130,18 @@ current directorys Cakefile.</p>
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-2">&#x00a7;</a>
</div>
<p>External dependencies.</p>
</div>
<div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
optparse = <span class="hljs-built_in">require</span> <span class="hljs-string">'./optparse'</span>
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./'</span></pre></div></div>
<div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;fs&#x27;</span>
path = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;path&#x27;</span>
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./helpers&#x27;</span>
optparse = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./optparse&#x27;</span>
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./&#x27;</span></pre></div></div>
</li>
@@ -149,8 +149,8 @@ CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-stri
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-3">&#x00a7;</a>
</div>
<p>Register .coffee extension</p>
@@ -164,8 +164,8 @@ CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-stri
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-4">&#x00a7;</a>
</div>
<p>Keep track of the list of defined tasks, the accepted options, and so on.</p>
@@ -182,14 +182,14 @@ oparse = <span class="hljs-literal">null</span></pre></div></div>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-5">&#x00a7;</a>
</div>
<p>Mixin the top-level Cake functions for Cakefiles to use directly.</p>
</div>
<div class="content"><div class='highlight'><pre>helpers.extend <span class="hljs-built_in">global</span>,</pre></div></div>
<div class="content"><div class='highlight'><pre>helpers.extend global,</pre></div></div>
</li>
@@ -197,8 +197,8 @@ oparse = <span class="hljs-literal">null</span></pre></div></div>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-6">&#x00a7;</a>
</div>
<p>Define a Cake task with a short name, an optional sentence description,
and the function to run as the action itself.</p>
@@ -215,8 +215,8 @@ and the function to run as the action itself.</p>
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-7">&#x00a7;</a>
</div>
<p>Define an option that the Cakefile accepts. The parsed options hash,
containing all of the command-line options passed, will be made available
@@ -233,8 +233,8 @@ as the first argument to the action.</p>
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-8">&#x00a7;</a>
</div>
<p>Invoke another task in the current Cakefile.</p>
@@ -250,8 +250,8 @@ as the first argument to the action.</p>
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-9">&#x00a7;</a>
</div>
<p>Run <code>cake</code>. Executes all of the tasks you pass, in order. Note that Nodes
asynchrony may cause tasks to execute in a different order than youd expect.
@@ -260,17 +260,17 @@ original directory name, when running Cake tasks from subdirectories.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.run = <span class="hljs-function">-&gt;</span>
<span class="hljs-built_in">global</span>.__originalDirname = fs.realpathSync <span class="hljs-string">'.'</span>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.run = <span class="hljs-function">-&gt;</span>
global.__originalDirname = fs.realpathSync <span class="hljs-string">&#x27;.&#x27;</span>
process.chdir cakefileDirectory __originalDirname
args = process.argv[<span class="hljs-number">2.</span>.]
CoffeeScript.run fs.readFileSync(<span class="hljs-string">'Cakefile'</span>).toString(), filename: <span class="hljs-string">'Cakefile'</span>
CoffeeScript.run fs.readFileSync(<span class="hljs-string">&#x27;Cakefile&#x27;</span>).toString(), filename: <span class="hljs-string">&#x27;Cakefile&#x27;</span>
oparse = <span class="hljs-keyword">new</span> optparse.OptionParser switches
<span class="hljs-keyword">return</span> printTasks() <span class="hljs-keyword">unless</span> args.length
<span class="hljs-keyword">try</span>
options = oparse.parse(args)
<span class="hljs-keyword">catch</span> e
<span class="hljs-keyword">return</span> fatalError <span class="hljs-string">"<span class="hljs-subst">#{e}</span>"</span>
<span class="hljs-keyword">return</span> fatalError <span class="hljs-string">&quot;<span class="hljs-subst">#{e}</span>&quot;</span>
invoke arg <span class="hljs-keyword">for</span> arg <span class="hljs-keyword">in</span> options.arguments</pre></div></div>
</li>
@@ -279,8 +279,8 @@ original directory name, when running Cake tasks from subdirectories.</p>
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-10">&#x00a7;</a>
</div>
<p>Display the list of Cake tasks in a format similar to <code>rake -T</code></p>
@@ -288,14 +288,14 @@ original directory name, when running Cake tasks from subdirectories.</p>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">printTasks</span> = -&gt;</span>
relative = path.relative <span class="hljs-keyword">or</span> path.resolve
cakefilePath = path.join relative(__originalDirname, process.cwd()), <span class="hljs-string">'Cakefile'</span>
<span class="hljs-built_in">console</span>.log <span class="hljs-string">"<span class="hljs-subst">#{cakefilePath}</span> defines the following tasks:\n"</span>
cakefilePath = path.join relative(__originalDirname, process.cwd()), <span class="hljs-string">&#x27;Cakefile&#x27;</span>
console.log <span class="hljs-string">&quot;<span class="hljs-subst">#{cakefilePath}</span> defines the following tasks:\n&quot;</span>
<span class="hljs-keyword">for</span> name, task <span class="hljs-keyword">of</span> tasks
spaces = <span class="hljs-number">20</span> - name.length
spaces = <span class="hljs-keyword">if</span> spaces &gt; <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> Array(spaces + <span class="hljs-number">1</span>).join(<span class="hljs-string">' '</span>) <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>
desc = <span class="hljs-keyword">if</span> task.description <span class="hljs-keyword">then</span> <span class="hljs-string">"# <span class="hljs-subst">#{task.description}</span>"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>
<span class="hljs-built_in">console</span>.log <span class="hljs-string">"cake <span class="hljs-subst">#{name}</span><span class="hljs-subst">#{spaces}</span> <span class="hljs-subst">#{desc}</span>"</span>
<span class="hljs-built_in">console</span>.log oparse.help() <span class="hljs-keyword">if</span> switches.length</pre></div></div>
spaces = <span class="hljs-keyword">if</span> spaces &gt; <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> <span class="hljs-built_in">Array</span>(spaces + <span class="hljs-number">1</span>).join(<span class="hljs-string">&#x27; &#x27;</span>) <span class="hljs-keyword">else</span> <span class="hljs-string">&#x27;&#x27;</span>
desc = <span class="hljs-keyword">if</span> task.description <span class="hljs-keyword">then</span> <span class="hljs-string">&quot;# <span class="hljs-subst">#{task.description}</span>&quot;</span> <span class="hljs-keyword">else</span> <span class="hljs-string">&#x27;&#x27;</span>
console.log <span class="hljs-string">&quot;cake <span class="hljs-subst">#{name}</span><span class="hljs-subst">#{spaces}</span> <span class="hljs-subst">#{desc}</span>&quot;</span>
console.log oparse.help() <span class="hljs-keyword">if</span> switches.length</pre></div></div>
</li>
@@ -303,19 +303,19 @@ original directory name, when running Cake tasks from subdirectories.</p>
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-11">&#x00a7;</a>
</div>
<p>Print an error and exit when attempting to use an invalid task/option.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">fatalError</span> = <span class="hljs-params">(message)</span> -&gt;</span>
<span class="hljs-built_in">console</span>.error message + <span class="hljs-string">'\n'</span>
<span class="hljs-built_in">console</span>.log <span class="hljs-string">'To see a list of all tasks/options, run "cake"'</span>
console.error message + <span class="hljs-string">&#x27;\n&#x27;</span>
console.log <span class="hljs-string">&#x27;To see a list of all tasks/options, run &quot;cake&quot;&#x27;</span>
process.exit <span class="hljs-number">1</span>
<span class="hljs-function">
<span class="hljs-title">missingTask</span> = <span class="hljs-params">(task)</span> -&gt;</span> fatalError <span class="hljs-string">"No such task: <span class="hljs-subst">#{task}</span>"</span></pre></div></div>
<span class="hljs-title">missingTask</span> = <span class="hljs-params">(task)</span> -&gt;</span> fatalError <span class="hljs-string">&quot;No such task: <span class="hljs-subst">#{task}</span>&quot;</span></pre></div></div>
</li>
@@ -323,8 +323,8 @@ original directory name, when running Cake tasks from subdirectories.</p>
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-12">&#x00a7;</a>
</div>
<p>When <code>cake</code> is invoked, search in the current and all parent directories
to find the relevant Cakefile.</p>
@@ -332,10 +332,10 @@ to find the relevant Cakefile.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">cakefileDirectory</span> = <span class="hljs-params">(dir)</span> -&gt;</span>
<span class="hljs-keyword">return</span> dir <span class="hljs-keyword">if</span> fs.existsSync path.join dir, <span class="hljs-string">'Cakefile'</span>
parent = path.normalize path.join dir, <span class="hljs-string">'..'</span>
<span class="hljs-keyword">return</span> dir <span class="hljs-keyword">if</span> fs.existsSync path.join dir, <span class="hljs-string">&#x27;Cakefile&#x27;</span>
parent = path.normalize path.join dir, <span class="hljs-string">&#x27;..&#x27;</span>
<span class="hljs-keyword">return</span> cakefileDirectory parent <span class="hljs-keyword">unless</span> parent <span class="hljs-keyword">is</span> dir
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"Cakefile not found in <span class="hljs-subst">#{process.cwd()}</span>"</span></pre></div></div>
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">&quot;Cakefile not found in <span class="hljs-subst">#{process.cwd()}</span>&quot;</span></pre></div></div>
</li>

File diff suppressed because it is too large Load Diff

View File

@@ -112,8 +112,8 @@
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-1">&#x00a7;</a>
</div>
<p>The <code>coffee</code> utility. Handles command-line compilation of CoffeeScript
into various forms: saved into <code>.js</code> files or printed to stdout
@@ -129,22 +129,22 @@ interactive REPL.</p>
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-2">&#x00a7;</a>
</div>
<p>External dependencies.</p>
</div>
<div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
optparse = <span class="hljs-built_in">require</span> <span class="hljs-string">'./optparse'</span>
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./'</span>
{spawn, exec} = <span class="hljs-built_in">require</span> <span class="hljs-string">'child_process'</span>
{EventEmitter} = <span class="hljs-built_in">require</span> <span class="hljs-string">'events'</span>
<div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;fs&#x27;</span>
path = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;path&#x27;</span>
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./helpers&#x27;</span>
optparse = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./optparse&#x27;</span>
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./&#x27;</span>
{spawn, exec} = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;child_process&#x27;</span>
{EventEmitter} = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;events&#x27;</span>
useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs-string">'\\'</span></pre></div></div>
useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;\\&#x27;</span></pre></div></div>
</li>
@@ -152,8 +152,8 @@ useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-3">&#x00a7;</a>
</div>
<p>Allow CoffeeScript to emit Node.js events.</p>
@@ -161,8 +161,8 @@ useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs
<div class="content"><div class='highlight'><pre>helpers.extend CoffeeScript, <span class="hljs-keyword">new</span> EventEmitter
<span class="hljs-function">
<span class="hljs-title">printLine</span> = <span class="hljs-params">(line)</span> -&gt;</span> process.stdout.write line + <span class="hljs-string">'\n'</span>
<span class="hljs-function"><span class="hljs-title">printWarn</span> = <span class="hljs-params">(line)</span> -&gt;</span> process.stderr.write line + <span class="hljs-string">'\n'</span>
<span class="hljs-title">printLine</span> = <span class="hljs-params">(line)</span> -&gt;</span> process.stdout.write line + <span class="hljs-string">&#x27;\n&#x27;</span>
<span class="hljs-function"><span class="hljs-title">printWarn</span> = <span class="hljs-params">(line)</span> -&gt;</span> process.stderr.write line + <span class="hljs-string">&#x27;\n&#x27;</span>
<span class="hljs-function">
<span class="hljs-title">hidden</span> = <span class="hljs-params">(file)</span> -&gt;</span> <span class="hljs-regexp">/^\.|~$/</span>.test file</pre></div></div>
@@ -172,18 +172,18 @@ useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-4">&#x00a7;</a>
</div>
<p>The help banner that is printed in conjunction with <code>-h</code>/<code>--help</code>.</p>
</div>
<div class="content"><div class='highlight'><pre>BANNER = <span class="hljs-string">'''
<div class="content"><div class='highlight'><pre>BANNER = <span class="hljs-string">&#x27;&#x27;&#x27;
Usage: coffee [options] path/to/script.coffee [args]
If called without options, `coffee` will run your script.
'''</span></pre></div></div>
&#x27;&#x27;&#x27;</span></pre></div></div>
</li>
@@ -191,34 +191,35 @@ useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-5">&#x00a7;</a>
</div>
<p>The list of all the valid option flags that <code>coffee</code> knows how to handle.</p>
</div>
<div class="content"><div class='highlight'><pre>SWITCHES = [
[<span class="hljs-string">'-b'</span>, <span class="hljs-string">'--bare'</span>, <span class="hljs-string">'compile without a top-level function wrapper'</span>]
[<span class="hljs-string">'-c'</span>, <span class="hljs-string">'--compile'</span>, <span class="hljs-string">'compile to JavaScript and save as .js files'</span>]
[<span class="hljs-string">'-e'</span>, <span class="hljs-string">'--eval'</span>, <span class="hljs-string">'pass a string from the command line as input'</span>]
[<span class="hljs-string">'-h'</span>, <span class="hljs-string">'--help'</span>, <span class="hljs-string">'display this help message'</span>]
[<span class="hljs-string">'-i'</span>, <span class="hljs-string">'--interactive'</span>, <span class="hljs-string">'run an interactive CoffeeScript REPL'</span>]
[<span class="hljs-string">'-j'</span>, <span class="hljs-string">'--join [FILE]'</span>, <span class="hljs-string">'concatenate the source CoffeeScript before compiling'</span>]
[<span class="hljs-string">'-m'</span>, <span class="hljs-string">'--map'</span>, <span class="hljs-string">'generate source map and save as .js.map files'</span>]
[<span class="hljs-string">'-M'</span>, <span class="hljs-string">'--inline-map'</span>, <span class="hljs-string">'generate source map and include it directly in output'</span>]
[<span class="hljs-string">'-n'</span>, <span class="hljs-string">'--nodes'</span>, <span class="hljs-string">'print out the parse tree that the parser produces'</span>]
[ <span class="hljs-string">'--nodejs [ARGS]'</span>, <span class="hljs-string">'pass options directly to the "node" binary'</span>]
[ <span class="hljs-string">'--no-header'</span>, <span class="hljs-string">'suppress the "Generated by" header'</span>]
[<span class="hljs-string">'-o'</span>, <span class="hljs-string">'--output [PATH]'</span>, <span class="hljs-string">'set the output path or path/filename for compiled JavaScript'</span>]
[<span class="hljs-string">'-p'</span>, <span class="hljs-string">'--print'</span>, <span class="hljs-string">'print out the compiled JavaScript'</span>]
[<span class="hljs-string">'-r'</span>, <span class="hljs-string">'--require [MODULE*]'</span>, <span class="hljs-string">'require the given module before eval or REPL'</span>]
[<span class="hljs-string">'-s'</span>, <span class="hljs-string">'--stdio'</span>, <span class="hljs-string">'listen for and compile scripts over stdio'</span>]
[<span class="hljs-string">'-l'</span>, <span class="hljs-string">'--literate'</span>, <span class="hljs-string">'treat stdio as literate style coffeescript'</span>]
[<span class="hljs-string">'-t'</span>, <span class="hljs-string">'--transpile'</span>, <span class="hljs-string">'pipe generated JavaScript through Babel'</span>]
[ <span class="hljs-string">'--tokens'</span>, <span class="hljs-string">'print out the tokens that the lexer/rewriter produce'</span>]
[<span class="hljs-string">'-v'</span>, <span class="hljs-string">'--version'</span>, <span class="hljs-string">'display the version number'</span>]
[<span class="hljs-string">'-w'</span>, <span class="hljs-string">'--watch'</span>, <span class="hljs-string">'watch scripts for changes and rerun commands'</span>]
[ <span class="hljs-string">&#x27;--ast&#x27;</span>, <span class="hljs-string">&#x27;generate an abstract syntax tree of nodes&#x27;</span>]
[<span class="hljs-string">&#x27;-b&#x27;</span>, <span class="hljs-string">&#x27;--bare&#x27;</span>, <span class="hljs-string">&#x27;compile without a top-level function wrapper&#x27;</span>]
[<span class="hljs-string">&#x27;-c&#x27;</span>, <span class="hljs-string">&#x27;--compile&#x27;</span>, <span class="hljs-string">&#x27;compile to JavaScript and save as .js files&#x27;</span>]
[<span class="hljs-string">&#x27;-e&#x27;</span>, <span class="hljs-string">&#x27;--eval&#x27;</span>, <span class="hljs-string">&#x27;pass a string from the command line as input&#x27;</span>]
[<span class="hljs-string">&#x27;-h&#x27;</span>, <span class="hljs-string">&#x27;--help&#x27;</span>, <span class="hljs-string">&#x27;display this help message&#x27;</span>]
[<span class="hljs-string">&#x27;-i&#x27;</span>, <span class="hljs-string">&#x27;--interactive&#x27;</span>, <span class="hljs-string">&#x27;run an interactive CoffeeScript REPL&#x27;</span>]
[<span class="hljs-string">&#x27;-j&#x27;</span>, <span class="hljs-string">&#x27;--join [FILE]&#x27;</span>, <span class="hljs-string">&#x27;concatenate the source CoffeeScript before compiling&#x27;</span>]
[<span class="hljs-string">&#x27;-l&#x27;</span>, <span class="hljs-string">&#x27;--literate&#x27;</span>, <span class="hljs-string">&#x27;treat stdio as literate style coffeescript&#x27;</span>]
[<span class="hljs-string">&#x27;-m&#x27;</span>, <span class="hljs-string">&#x27;--map&#x27;</span>, <span class="hljs-string">&#x27;generate source map and save as .js.map files&#x27;</span>]
[<span class="hljs-string">&#x27;-M&#x27;</span>, <span class="hljs-string">&#x27;--inline-map&#x27;</span>, <span class="hljs-string">&#x27;generate source map and include it directly in output&#x27;</span>]
[<span class="hljs-string">&#x27;-n&#x27;</span>, <span class="hljs-string">&#x27;--nodes&#x27;</span>, <span class="hljs-string">&#x27;print out the parse tree that the parser produces&#x27;</span>]
[ <span class="hljs-string">&#x27;--nodejs [ARGS]&#x27;</span>, <span class="hljs-string">&#x27;pass options directly to the &quot;node&quot; binary&#x27;</span>]
[ <span class="hljs-string">&#x27;--no-header&#x27;</span>, <span class="hljs-string">&#x27;suppress the &quot;Generated by&quot; header&#x27;</span>]
[<span class="hljs-string">&#x27;-o&#x27;</span>, <span class="hljs-string">&#x27;--output [PATH]&#x27;</span>, <span class="hljs-string">&#x27;set the output path or path/filename for compiled JavaScript&#x27;</span>]
[<span class="hljs-string">&#x27;-p&#x27;</span>, <span class="hljs-string">&#x27;--print&#x27;</span>, <span class="hljs-string">&#x27;print out the compiled JavaScript&#x27;</span>]
[<span class="hljs-string">&#x27;-r&#x27;</span>, <span class="hljs-string">&#x27;--require [MODULE*]&#x27;</span>, <span class="hljs-string">&#x27;require the given module before eval or REPL&#x27;</span>]
[<span class="hljs-string">&#x27;-s&#x27;</span>, <span class="hljs-string">&#x27;--stdio&#x27;</span>, <span class="hljs-string">&#x27;listen for and compile scripts over stdio&#x27;</span>]
[<span class="hljs-string">&#x27;-t&#x27;</span>, <span class="hljs-string">&#x27;--transpile&#x27;</span>, <span class="hljs-string">&#x27;pipe generated JavaScript through Babel&#x27;</span>]
[ <span class="hljs-string">&#x27;--tokens&#x27;</span>, <span class="hljs-string">&#x27;print out the tokens that the lexer/rewriter produce&#x27;</span>]
[<span class="hljs-string">&#x27;-v&#x27;</span>, <span class="hljs-string">&#x27;--version&#x27;</span>, <span class="hljs-string">&#x27;display the version number&#x27;</span>]
[<span class="hljs-string">&#x27;-w&#x27;</span>, <span class="hljs-string">&#x27;--watch&#x27;</span>, <span class="hljs-string">&#x27;watch scripts for changes and rerun commands&#x27;</span>]
]</pre></div></div>
</li>
@@ -227,8 +228,8 @@ useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-6">&#x00a7;</a>
</div>
<p>Top-level objects shared by all the functions.</p>
@@ -241,7 +242,7 @@ notSources = {}
watchedDirs = {}
optionParser = <span class="hljs-literal">null</span>
exports.buildCSOptionParser = buildCSOptionParser = <span class="hljs-function">-&gt;</span>
<span class="hljs-built_in">exports</span>.buildCSOptionParser = buildCSOptionParser = <span class="hljs-function">-&gt;</span>
<span class="hljs-keyword">new</span> optparse.OptionParser SWITCHES, BANNER</pre></div></div>
</li>
@@ -250,8 +251,8 @@ exports.buildCSOptionParser = buildCSOptionParser = <span class="hljs-function">
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-7">&#x00a7;</a>
</div>
<p>Run <code>coffee</code> by parsing passed options and determining what action to take.
Many flags cause us to divert before compiling anything. Flags passed after
@@ -259,22 +260,22 @@ Many flags cause us to divert before compiling anything. Flags passed after
</div>
<div class="content"><div class='highlight'><pre>exports.run = <span class="hljs-function">-&gt;</span>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.run = <span class="hljs-function">-&gt;</span>
optionParser = buildCSOptionParser()
<span class="hljs-keyword">try</span> parseOptions()
<span class="hljs-keyword">catch</span> err
<span class="hljs-built_in">console</span>.error <span class="hljs-string">"option parsing error: <span class="hljs-subst">#{err.message}</span>"</span>
console.error <span class="hljs-string">&quot;option parsing error: <span class="hljs-subst">#{err.message}</span>&quot;</span>
process.exit <span class="hljs-number">1</span>
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">not</span> opts.doubleDashed) <span class="hljs-keyword">and</span> (opts.arguments[<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'--'</span>)
printWarn <span class="hljs-string">'''
coffee was invoked with '--' as the second positional argument, which is
now deprecated. To pass '--' as an argument to a script to run, put an
additional '--' before the path to your script.
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">not</span> opts.doubleDashed) <span class="hljs-keyword">and</span> (opts.arguments[<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;--&#x27;</span>)
printWarn <span class="hljs-string">&#x27;&#x27;&#x27;
coffee was invoked with &#x27;--&#x27; as the second positional argument, which is
now deprecated. To pass &#x27;--&#x27; as an argument to a script to run, put an
additional &#x27;--&#x27; before the path to your script.
'--' will be removed from the argument list.
'''</span>
printWarn <span class="hljs-string">"The positional arguments were: <span class="hljs-subst">#{JSON.stringify opts.arguments}</span>"</span>
&#x27;--&#x27; will be removed from the argument list.
&#x27;&#x27;&#x27;</span>
printWarn <span class="hljs-string">&quot;The positional arguments were: <span class="hljs-subst">#{<span class="hljs-built_in">JSON</span>.stringify opts.arguments}</span>&quot;</span>
opts.arguments = [opts.arguments[<span class="hljs-number">0</span>]].concat opts.arguments[<span class="hljs-number">2.</span>.]</pre></div></div>
</li>
@@ -283,8 +284,8 @@ Many flags cause us to divert before compiling anything. Flags passed after
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-8">&#x00a7;</a>
</div>
<p>Make the REPL <em>CLI</em> use the global context so as to (a) be consistent with the
<code>node</code> REPL CLI and, therefore, (b) make packages that modify native prototypes
@@ -299,18 +300,18 @@ Many flags cause us to divert before compiling anything. Flags passed after
<span class="hljs-keyword">return</span> forkNode() <span class="hljs-keyword">if</span> opts.nodejs
<span class="hljs-keyword">return</span> usage() <span class="hljs-keyword">if</span> opts.help
<span class="hljs-keyword">return</span> version() <span class="hljs-keyword">if</span> opts.version
<span class="hljs-keyword">return</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./repl'</span>).start(replCliOpts) <span class="hljs-keyword">if</span> opts.interactive
<span class="hljs-keyword">return</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./repl&#x27;</span>).start(replCliOpts) <span class="hljs-keyword">if</span> opts.interactive
<span class="hljs-keyword">return</span> compileStdio() <span class="hljs-keyword">if</span> opts.stdio
<span class="hljs-keyword">return</span> compileScript <span class="hljs-literal">null</span>, opts.arguments[<span class="hljs-number">0</span>] <span class="hljs-keyword">if</span> opts.eval
<span class="hljs-keyword">return</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./repl'</span>).start(replCliOpts) <span class="hljs-keyword">unless</span> opts.arguments.length
<span class="hljs-keyword">return</span> compileScript <span class="hljs-literal">null</span>, opts.arguments[<span class="hljs-number">0</span>] <span class="hljs-keyword">if</span> opts.<span class="hljs-built_in">eval</span>
<span class="hljs-keyword">return</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./repl&#x27;</span>).start(replCliOpts) <span class="hljs-keyword">unless</span> opts.arguments.length
literals = <span class="hljs-keyword">if</span> opts.run <span class="hljs-keyword">then</span> opts.arguments.splice <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> []
process.argv = process.argv[<span class="hljs-number">0.</span><span class="hljs-number">.1</span>].concat literals
process.argv[<span class="hljs-number">0</span>] = <span class="hljs-string">'coffee'</span>
process.argv[<span class="hljs-number">0</span>] = <span class="hljs-string">&#x27;coffee&#x27;</span>
<span class="hljs-keyword">if</span> opts.output
outputBasename = path.basename opts.output
<span class="hljs-keyword">if</span> <span class="hljs-string">'.'</span> <span class="hljs-keyword">in</span> outputBasename <span class="hljs-keyword">and</span>
outputBasename <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'.'</span>, <span class="hljs-string">'..'</span>] <span class="hljs-keyword">and</span>
<span class="hljs-keyword">if</span> <span class="hljs-string">&#x27;.&#x27;</span> <span class="hljs-keyword">in</span> outputBasename <span class="hljs-keyword">and</span>
outputBasename <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">&#x27;.&#x27;</span>, <span class="hljs-string">&#x27;..&#x27;</span>] <span class="hljs-keyword">and</span>
<span class="hljs-keyword">not</span> helpers.ends(opts.output, path.sep)</pre></div></div>
</li>
@@ -319,8 +320,8 @@ Many flags cause us to divert before compiling anything. Flags passed after
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-9">&#x00a7;</a>
</div>
<p>An output filename was specified, e.g. <code>/dist/scripts.js</code>.</p>
@@ -336,8 +337,8 @@ Many flags cause us to divert before compiling anything. Flags passed after
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-10">&#x00a7;</a>
</div>
<p>An output path was specified, e.g. <code>/dist</code>.</p>
@@ -348,11 +349,11 @@ Many flags cause us to divert before compiling anything. Flags passed after
<span class="hljs-keyword">if</span> opts.join
opts.join = path.resolve opts.join
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'''
console.error <span class="hljs-string">&#x27;&#x27;&#x27;
The --join option is deprecated and will be removed in a future version.
If for some reason it's necessary to share local variables between files,
If for some reason it&#x27;s necessary to share local variables between files,
replace...
$ coffee --compile --join bundle.js -- a.coffee b.coffee c.coffee
@@ -361,17 +362,17 @@ Many flags cause us to divert before compiling anything. Flags passed after
$ cat a.coffee b.coffee c.coffee | coffee --compile --stdio &gt; bundle.js
'''</span>
&#x27;&#x27;&#x27;</span>
<span class="hljs-keyword">for</span> source <span class="hljs-keyword">in</span> opts.arguments
source = path.resolve source
compilePath source, <span class="hljs-literal">yes</span>, source
<span class="hljs-function">
<span class="hljs-title">makePrelude</span> = <span class="hljs-params">(requires)</span> -&gt;</span>
requires.map (<span class="hljs-built_in">module</span>) -&gt;
[full, name, <span class="hljs-built_in">module</span>] = match <span class="hljs-keyword">if</span> match = <span class="hljs-built_in">module</span>.match(<span class="hljs-regexp">/^(.*)=(.*)$/</span>)
name <span class="hljs-keyword">or</span>= helpers.baseFileName <span class="hljs-built_in">module</span>, <span class="hljs-literal">yes</span>, useWinPathSep
<span class="hljs-string">"global['<span class="hljs-subst">#{name}</span>'] = require('<span class="hljs-subst">#{<span class="hljs-built_in">module</span>}</span>')"</span>
.join <span class="hljs-string">';'</span></pre></div></div>
requires.map (module) -&gt;
[full, name, module] = match <span class="hljs-keyword">if</span> match = module.match(<span class="hljs-regexp">/^(.*)=(.*)$/</span>)
name <span class="hljs-keyword">or</span>= helpers.baseFileName module, <span class="hljs-literal">yes</span>, useWinPathSep
<span class="hljs-string">&quot;global[&#x27;<span class="hljs-subst">#{name}</span>&#x27;] = require(&#x27;<span class="hljs-subst">#{module}</span>&#x27;)&quot;</span>
.join <span class="hljs-string">&#x27;;&#x27;</span></pre></div></div>
</li>
@@ -379,8 +380,8 @@ Many flags cause us to divert before compiling anything. Flags passed after
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-11">&#x00a7;</a>
</div>
<p>Compile a path, which could be a script or a directory. If a directory
is passed, recursively compile all .coffee, .litcoffee, and .coffee.md
@@ -395,12 +396,12 @@ extension source files in it and all subdirectories.</p>
<span class="hljs-keyword">try</span>
stats = fs.statSync source
<span class="hljs-keyword">catch</span> err
<span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
<span class="hljs-built_in">console</span>.error <span class="hljs-string">"File not found: <span class="hljs-subst">#{source}</span>"</span>
<span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;ENOENT&#x27;</span>
console.error <span class="hljs-string">&quot;File not found: <span class="hljs-subst">#{source}</span>&quot;</span>
process.exit <span class="hljs-number">1</span>
<span class="hljs-keyword">throw</span> err
<span class="hljs-keyword">if</span> stats.isDirectory()
<span class="hljs-keyword">if</span> path.basename(source) <span class="hljs-keyword">is</span> <span class="hljs-string">'node_modules'</span>
<span class="hljs-keyword">if</span> path.basename(source) <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;node_modules&#x27;</span>
notSources[source] = <span class="hljs-literal">yes</span>
<span class="hljs-keyword">return</span>
<span class="hljs-keyword">if</span> opts.run
@@ -410,7 +411,7 @@ extension source files in it and all subdirectories.</p>
<span class="hljs-keyword">try</span>
files = fs.readdirSync source
<span class="hljs-keyword">catch</span> err
<span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span> err
<span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;ENOENT&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span> err
<span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> files
compilePath (path.join source, file), <span class="hljs-literal">no</span>, base
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> topLevel <span class="hljs-keyword">or</span> helpers.isCoffee source
@@ -421,19 +422,19 @@ extension source files in it and all subdirectories.</p>
<span class="hljs-keyword">try</span>
code = fs.readFileSync source
<span class="hljs-keyword">catch</span> err
<span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span> err
<span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;ENOENT&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span> err
compileScript source, code.toString(), base
<span class="hljs-keyword">else</span>
notSources[source] = <span class="hljs-literal">yes</span>
<span class="hljs-function">
<span class="hljs-title">findDirectoryIndex</span> = <span class="hljs-params">(source)</span> -&gt;</span>
<span class="hljs-keyword">for</span> ext <span class="hljs-keyword">in</span> CoffeeScript.FILE_EXTENSIONS
index = path.join source, <span class="hljs-string">"index<span class="hljs-subst">#{ext}</span>"</span>
index = path.join source, <span class="hljs-string">&quot;index<span class="hljs-subst">#{ext}</span>&quot;</span>
<span class="hljs-keyword">try</span>
<span class="hljs-keyword">return</span> index <span class="hljs-keyword">if</span> (fs.statSync index).isFile()
<span class="hljs-keyword">catch</span> err
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
<span class="hljs-built_in">console</span>.error <span class="hljs-string">"Missing index.coffee or index.litcoffee in <span class="hljs-subst">#{source}</span>"</span>
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;ENOENT&#x27;</span>
console.error <span class="hljs-string">&quot;Missing index.coffee or index.litcoffee in <span class="hljs-subst">#{source}</span>&quot;</span>
process.exit <span class="hljs-number">1</span></pre></div></div>
</li>
@@ -442,8 +443,8 @@ extension source files in it and all subdirectories.</p>
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-12">&#x00a7;</a>
</div>
<p>Compile a single source script, containing the given code, according to the
requested options. If evaluating the script directly, set <code>__filename</code>,
@@ -455,14 +456,17 @@ requested options. If evaluating the script directly, set <code>__filename</code
options = compileOptions file, base
<span class="hljs-keyword">try</span>
task = {file, input, options}
CoffeeScript.emit <span class="hljs-string">'compile'</span>, task
CoffeeScript.emit <span class="hljs-string">&#x27;compile&#x27;</span>, task
<span class="hljs-keyword">if</span> opts.tokens
printTokens CoffeeScript.tokens task.input, task.options
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.nodes
printLine CoffeeScript.nodes(task.input, task.options).toString().trim()
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.ast
compiled = CoffeeScript.compile task.input, task.options
printLine <span class="hljs-built_in">JSON</span>.stringify(compiled, <span class="hljs-literal">null</span>, <span class="hljs-number">2</span>)
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.run
CoffeeScript.register()
CoffeeScript.eval opts.prelude, task.options <span class="hljs-keyword">if</span> opts.prelude
CoffeeScript.<span class="hljs-built_in">eval</span> opts.prelude, task.options <span class="hljs-keyword">if</span> opts.prelude
CoffeeScript.run task.input, task.options
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.join <span class="hljs-keyword">and</span> task.file <span class="hljs-keyword">isnt</span> opts.join
task.input = helpers.invertLiterate task.input <span class="hljs-keyword">if</span> helpers.isLiterate file
@@ -475,7 +479,7 @@ requested options. If evaluating the script directly, set <code>__filename</code
task.output = compiled.js
task.sourceMap = compiled.v3SourceMap
CoffeeScript.emit <span class="hljs-string">'success'</span>, task
CoffeeScript.emit <span class="hljs-string">&#x27;success&#x27;</span>, task
<span class="hljs-keyword">if</span> opts.<span class="hljs-built_in">print</span>
printLine task.output.trim()
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.compile <span class="hljs-keyword">or</span> opts.map
@@ -485,11 +489,11 @@ requested options. If evaluating the script directly, set <code>__filename</code
options.jsPath
writeJs base, task.file, task.output, saveTo, task.sourceMap
<span class="hljs-keyword">catch</span> err
CoffeeScript.emit <span class="hljs-string">'failure'</span>, err, task
<span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> CoffeeScript.listeners(<span class="hljs-string">'failure'</span>).length
message = err?.stack <span class="hljs-keyword">or</span> <span class="hljs-string">"<span class="hljs-subst">#{err}</span>"</span>
CoffeeScript.emit <span class="hljs-string">&#x27;failure&#x27;</span>, err, task
<span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> CoffeeScript.listeners(<span class="hljs-string">&#x27;failure&#x27;</span>).length
message = err?.stack <span class="hljs-keyword">or</span> <span class="hljs-string">&quot;<span class="hljs-subst">#{err}</span>&quot;</span>
<span class="hljs-keyword">if</span> opts.watch
printLine message + <span class="hljs-string">'\x07'</span>
printLine message + <span class="hljs-string">&#x27;\x07&#x27;</span>
<span class="hljs-keyword">else</span>
printWarn message
process.exit <span class="hljs-number">1</span></pre></div></div>
@@ -500,8 +504,8 @@ requested options. If evaluating the script directly, set <code>__filename</code
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-13">&#x00a7;</a>
</div>
<p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
and write them back to <strong>stdout</strong>.</p>
@@ -510,13 +514,13 @@ and write them back to <strong>stdout</strong>.</p>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">compileStdio</span> = -&gt;</span>
<span class="hljs-keyword">if</span> opts.map
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'--stdio and --map cannot be used together'</span>
console.error <span class="hljs-string">&#x27;--stdio and --map cannot be used together&#x27;</span>
process.exit <span class="hljs-number">1</span>
buffers = []
stdin = process.openStdin()
stdin.<span class="hljs-literal">on</span> <span class="hljs-string">'data'</span>, <span class="hljs-function"><span class="hljs-params">(buffer)</span> -&gt;</span>
stdin.<span class="hljs-literal">on</span> <span class="hljs-string">&#x27;data&#x27;</span>, <span class="hljs-function"><span class="hljs-params">(buffer)</span> -&gt;</span>
buffers.push buffer <span class="hljs-keyword">if</span> buffer
stdin.<span class="hljs-literal">on</span> <span class="hljs-string">'end'</span>, <span class="hljs-function">-&gt;</span>
stdin.<span class="hljs-literal">on</span> <span class="hljs-string">&#x27;end&#x27;</span>, <span class="hljs-function">-&gt;</span>
compileScript <span class="hljs-literal">null</span>, Buffer.concat(buffers).toString()</pre></div></div>
</li>
@@ -525,8 +529,8 @@ and write them back to <strong>stdout</strong>.</p>
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-14">&#x00a7;</a>
</div>
<p>If all of the source files are done being read, concatenate and compile
them together.</p>
@@ -537,9 +541,9 @@ them together.</p>
<span class="hljs-function"><span class="hljs-title">compileJoin</span> = -&gt;</span>
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> opts.join
<span class="hljs-keyword">unless</span> sourceCode.some(<span class="hljs-function"><span class="hljs-params">(code)</span> -&gt;</span> code <span class="hljs-keyword">is</span> <span class="hljs-literal">null</span>)
clearTimeout joinTimeout
<span class="hljs-built_in">clearTimeout</span> joinTimeout
joinTimeout = wait <span class="hljs-number">100</span>, <span class="hljs-function">-&gt;</span>
compileScript opts.join, sourceCode.join(<span class="hljs-string">'\n'</span>), opts.join</pre></div></div>
compileScript opts.join, sourceCode.join(<span class="hljs-string">&#x27;\n&#x27;</span>), opts.join</pre></div></div>
</li>
@@ -547,8 +551,8 @@ them together.</p>
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-15">&#x00a7;</a>
</div>
<p>Watch a source CoffeeScript file using <code>fs.watch</code>, recompiling it every
time the file is updated. May be used in combination with other options,
@@ -562,7 +566,7 @@ such as <code>--print</code>.</p>
compileTimeout = <span class="hljs-literal">null</span>
<span class="hljs-function">
<span class="hljs-title">watchErr</span> = <span class="hljs-params">(err)</span> -&gt;</span>
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;ENOENT&#x27;</span>
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> source <span class="hljs-keyword">in</span> sources
<span class="hljs-keyword">try</span>
rewatch()
@@ -572,7 +576,7 @@ such as <code>--print</code>.</p>
compileJoin()
<span class="hljs-function">
<span class="hljs-title">compile</span> = -&gt;</span>
clearTimeout compileTimeout
<span class="hljs-built_in">clearTimeout</span> compileTimeout
compileTimeout = wait <span class="hljs-number">25</span>, <span class="hljs-function">-&gt;</span>
fs.stat source, <span class="hljs-function"><span class="hljs-params">(err, stats)</span> -&gt;</span>
<span class="hljs-keyword">return</span> watchErr err <span class="hljs-keyword">if</span> err
@@ -587,9 +591,9 @@ such as <code>--print</code>.</p>
<span class="hljs-function">
<span class="hljs-title">startWatcher</span> = -&gt;</span>
watcher = fs.watch source
.<span class="hljs-literal">on</span> <span class="hljs-string">'change'</span>, compile
.<span class="hljs-literal">on</span> <span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-params">(err)</span> -&gt;</span>
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'EPERM'</span>
.<span class="hljs-literal">on</span> <span class="hljs-string">&#x27;change&#x27;</span>, compile
.<span class="hljs-literal">on</span> <span class="hljs-string">&#x27;error&#x27;</span>, <span class="hljs-function"><span class="hljs-params">(err)</span> -&gt;</span>
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;EPERM&#x27;</span>
removeSource source, base
<span class="hljs-function">
<span class="hljs-title">rewatch</span> = -&gt;</span>
@@ -607,8 +611,8 @@ such as <code>--print</code>.</p>
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-16">&#x00a7;</a>
</div>
<p>Watch a directory of files for new additions.</p>
@@ -620,16 +624,16 @@ such as <code>--print</code>.</p>
<span class="hljs-function">
<span class="hljs-title">startWatcher</span> = -&gt;</span>
watcher = fs.watch source
.<span class="hljs-literal">on</span> <span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-params">(err)</span> -&gt;</span>
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'EPERM'</span>
.<span class="hljs-literal">on</span> <span class="hljs-string">&#x27;error&#x27;</span>, <span class="hljs-function"><span class="hljs-params">(err)</span> -&gt;</span>
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;EPERM&#x27;</span>
stopWatcher()
.<span class="hljs-literal">on</span> <span class="hljs-string">'change'</span>, <span class="hljs-function">-&gt;</span>
clearTimeout readdirTimeout
.<span class="hljs-literal">on</span> <span class="hljs-string">&#x27;change&#x27;</span>, <span class="hljs-function">-&gt;</span>
<span class="hljs-built_in">clearTimeout</span> readdirTimeout
readdirTimeout = wait <span class="hljs-number">25</span>, <span class="hljs-function">-&gt;</span>
<span class="hljs-keyword">try</span>
files = fs.readdirSync source
<span class="hljs-keyword">catch</span> err
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;ENOENT&#x27;</span>
<span class="hljs-keyword">return</span> stopWatcher()
<span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> files
compilePath (path.join source, file), <span class="hljs-literal">no</span>, base
@@ -642,7 +646,7 @@ such as <code>--print</code>.</p>
<span class="hljs-keyword">try</span>
startWatcher()
<span class="hljs-keyword">catch</span> err
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span>
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;ENOENT&#x27;</span>
<span class="hljs-function">
<span class="hljs-title">removeSourceDir</span> = <span class="hljs-params">(source, base)</span> -&gt;</span>
<span class="hljs-keyword">delete</span> watchedDirs[source]
@@ -658,8 +662,8 @@ such as <code>--print</code>.</p>
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-17">&#x00a7;</a>
</div>
<p>Remove a file from our source list, and source code cache. Optionally remove
the compiled JS version as well.</p>
@@ -672,14 +676,14 @@ the compiled JS version as well.</p>
sourceCode.splice index, <span class="hljs-number">1</span>
<span class="hljs-keyword">unless</span> opts.join
silentUnlink outputPath source, base
silentUnlink outputPath source, base, <span class="hljs-string">'.js.map'</span>
timeLog <span class="hljs-string">"removed <span class="hljs-subst">#{source}</span>"</span>
silentUnlink outputPath source, base, <span class="hljs-string">&#x27;.js.map&#x27;</span>
timeLog <span class="hljs-string">&quot;removed <span class="hljs-subst">#{source}</span>&quot;</span>
<span class="hljs-function">
<span class="hljs-title">silentUnlink</span> = <span class="hljs-params">(path)</span> -&gt;</span>
<span class="hljs-keyword">try</span>
fs.unlinkSync path
<span class="hljs-keyword">catch</span> err
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">in</span> [<span class="hljs-string">'ENOENT'</span>, <span class="hljs-string">'EPERM'</span>]</pre></div></div>
<span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">in</span> [<span class="hljs-string">&#x27;ENOENT&#x27;</span>, <span class="hljs-string">&#x27;EPERM&#x27;</span>]</pre></div></div>
</li>
@@ -687,14 +691,14 @@ the compiled JS version as well.</p>
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-18">&#x00a7;</a>
</div>
<p>Get the corresponding output JavaScript path for a source file.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">outputPath</span> = <span class="hljs-params">(source, base, extension=<span class="hljs-string">".js"</span>)</span> -&gt;</span>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">outputPath</span> = <span class="hljs-params">(source, base, extension=<span class="hljs-string">&quot;.js&quot;</span>)</span> -&gt;</span>
basename = helpers.baseFileName source, <span class="hljs-literal">yes</span>, useWinPathSep
srcDir = path.dirname source
dir = <span class="hljs-keyword">unless</span> opts.outputPath
@@ -711,8 +715,8 @@ the compiled JS version as well.</p>
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-19">&#x00a7;</a>
</div>
<p>Recursively mkdir, like <code>mkdir -p</code>.</p>
@@ -737,8 +741,8 @@ the compiled JS version as well.</p>
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-20">&#x00a7;</a>
</div>
<p>Write out a JavaScript source file with the compiled code. By default, files
are written out in <code>cwd</code> as <code>.js</code> files with the same name, but the output
@@ -749,22 +753,22 @@ same directory as the <code>.js</code> file.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">writeJs</span> = <span class="hljs-params">(base, sourcePath, js, jsPath, generatedSourceMap = <span class="hljs-literal">null</span>)</span> -&gt;</span>
sourceMapPath = <span class="hljs-string">"<span class="hljs-subst">#{jsPath}</span>.map"</span>
sourceMapPath = <span class="hljs-string">&quot;<span class="hljs-subst">#{jsPath}</span>.map&quot;</span>
jsDir = path.dirname jsPath
<span class="hljs-function"> <span class="hljs-title">compile</span> = -&gt;</span>
<span class="hljs-keyword">if</span> opts.compile
js = <span class="hljs-string">' '</span> <span class="hljs-keyword">if</span> js.length &lt;= <span class="hljs-number">0</span>
<span class="hljs-keyword">if</span> generatedSourceMap <span class="hljs-keyword">then</span> js = <span class="hljs-string">"<span class="hljs-subst">#{js}</span>\n//# sourceMappingURL=<span class="hljs-subst">#{helpers.baseFileName sourceMapPath, <span class="hljs-literal">no</span>, useWinPathSep}</span>\n"</span>
js = <span class="hljs-string">&#x27; &#x27;</span> <span class="hljs-keyword">if</span> js.length &lt;= <span class="hljs-number">0</span>
<span class="hljs-keyword">if</span> generatedSourceMap <span class="hljs-keyword">then</span> js = <span class="hljs-string">&quot;<span class="hljs-subst">#{js}</span>\n//# sourceMappingURL=<span class="hljs-subst">#{helpers.baseFileName sourceMapPath, <span class="hljs-literal">no</span>, useWinPathSep}</span>\n&quot;</span>
fs.writeFile jsPath, js, <span class="hljs-function"><span class="hljs-params">(err)</span> -&gt;</span>
<span class="hljs-keyword">if</span> err
printLine err.message
process.exit <span class="hljs-number">1</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.compile <span class="hljs-keyword">and</span> opts.watch
timeLog <span class="hljs-string">"compiled <span class="hljs-subst">#{sourcePath}</span>"</span>
timeLog <span class="hljs-string">&quot;compiled <span class="hljs-subst">#{sourcePath}</span>&quot;</span>
<span class="hljs-keyword">if</span> generatedSourceMap
fs.writeFile sourceMapPath, generatedSourceMap, <span class="hljs-function"><span class="hljs-params">(err)</span> -&gt;</span>
<span class="hljs-keyword">if</span> err
printLine <span class="hljs-string">"Could not write source map: <span class="hljs-subst">#{err.message}</span>"</span>
printLine <span class="hljs-string">&quot;Could not write source map: <span class="hljs-subst">#{err.message}</span>&quot;</span>
process.exit <span class="hljs-number">1</span>
fs.exists jsDir, <span class="hljs-function"><span class="hljs-params">(itExists)</span> -&gt;</span>
<span class="hljs-keyword">if</span> itExists <span class="hljs-keyword">then</span> compile() <span class="hljs-keyword">else</span> mkdirp jsDir, compile</pre></div></div>
@@ -775,14 +779,14 @@ same directory as the <code>.js</code> file.</p>
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-21">&#x00a7;</a>
</div>
<p>Convenience for cleaner setTimeouts.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">wait</span> = <span class="hljs-params">(milliseconds, func)</span> -&gt;</span> setTimeout func, milliseconds</pre></div></div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">wait</span> = <span class="hljs-params">(milliseconds, func)</span> -&gt;</span> <span class="hljs-built_in">setTimeout</span> func, milliseconds</pre></div></div>
</li>
@@ -790,15 +794,15 @@ same directory as the <code>.js</code> file.</p>
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-22">&#x00a7;</a>
</div>
<p>When watching scripts, its useful to log changes with the timestamp.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">timeLog</span> = <span class="hljs-params">(message)</span> -&gt;</span>
<span class="hljs-built_in">console</span>.log <span class="hljs-string">"<span class="hljs-subst">#{(<span class="hljs-keyword">new</span> Date).toLocaleTimeString()}</span> - <span class="hljs-subst">#{message}</span>"</span></pre></div></div>
console.log <span class="hljs-string">&quot;<span class="hljs-subst">#{(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>).toLocaleTimeString()}</span> - <span class="hljs-subst">#{message}</span>&quot;</span></pre></div></div>
</li>
@@ -806,8 +810,8 @@ same directory as the <code>.js</code> file.</p>
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-23">&#x00a7;</a>
</div>
<p>Pretty-print a stream of tokens, sans location data.</p>
@@ -816,9 +820,9 @@ same directory as the <code>.js</code> file.</p>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">printTokens</span> = <span class="hljs-params">(tokens)</span> -&gt;</span>
strings = <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens
tag = token[<span class="hljs-number">0</span>]
value = token[<span class="hljs-number">1</span>].toString().replace(<span class="hljs-regexp">/\n/</span>, <span class="hljs-string">'\\n'</span>)
<span class="hljs-string">"[<span class="hljs-subst">#{tag}</span> <span class="hljs-subst">#{value}</span>]"</span>
printLine strings.join(<span class="hljs-string">' '</span>)</pre></div></div>
value = token[<span class="hljs-number">1</span>].toString().replace(<span class="hljs-regexp">/\n/</span>, <span class="hljs-string">&#x27;\\n&#x27;</span>)
<span class="hljs-string">&quot;[<span class="hljs-subst">#{tag}</span> <span class="hljs-subst">#{value}</span>]&quot;</span>
printLine strings.join(<span class="hljs-string">&#x27; &#x27;</span>)</pre></div></div>
</li>
@@ -826,8 +830,8 @@ same directory as the <code>.js</code> file.</p>
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-24">&#x00a7;</a>
</div>
<p>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
<code>process.argv</code> that are specified in <code>SWITCHES</code>.</p>
@@ -838,7 +842,7 @@ same directory as the <code>.js</code> file.</p>
o = opts = optionParser.parse process.argv[<span class="hljs-number">2.</span>.]
o.compile <span class="hljs-keyword">or</span>= !!o.output
o.run = <span class="hljs-keyword">not</span> (o.compile <span class="hljs-keyword">or</span> o.<span class="hljs-built_in">print</span> <span class="hljs-keyword">or</span> o.map)
o.<span class="hljs-built_in">print</span> = !! (o.<span class="hljs-built_in">print</span> <span class="hljs-keyword">or</span> (o.eval <span class="hljs-keyword">or</span> o.stdio <span class="hljs-keyword">and</span> o.compile))</pre></div></div>
o.<span class="hljs-built_in">print</span> = !! (o.<span class="hljs-built_in">print</span> <span class="hljs-keyword">or</span> (o.<span class="hljs-built_in">eval</span> <span class="hljs-keyword">or</span> o.stdio <span class="hljs-keyword">and</span> o.compile))</pre></div></div>
</li>
@@ -846,8 +850,8 @@ same directory as the <code>.js</code> file.</p>
<li id="section-25">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-25">&#x00a7;</a>
</div>
<p>The compile-time options to pass to the CoffeeScript compiler.</p>
@@ -862,8 +866,8 @@ same directory as the <code>.js</code> file.</p>
<li id="section-26">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-26">&#x00a7;</a>
</div>
<p>The user has requested that the CoffeeScript compiler also transpile
via Babel. We dont include Babel as a dependency because we want to
@@ -875,10 +879,10 @@ browsers) or use a proper build chain like Gulp or Webpack.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">try</span>
<span class="hljs-built_in">require</span> <span class="hljs-string">'@babel/core'</span>
<span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;@babel/core&#x27;</span>
<span class="hljs-keyword">catch</span>
<span class="hljs-keyword">try</span>
<span class="hljs-built_in">require</span> <span class="hljs-string">'babel-core'</span>
<span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;babel-core&#x27;</span>
<span class="hljs-keyword">catch</span></pre></div></div>
</li>
@@ -887,31 +891,31 @@ browsers) or use a proper build chain like Gulp or Webpack.</p>
<li id="section-27">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-27">&#x00a7;</a>
</div>
<p>Give appropriate instructions depending on whether <code>coffee</code> was run
locally or globally.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> <span class="hljs-built_in">require</span>.resolve(<span class="hljs-string">'.'</span>).indexOf(process.cwd()) <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'''
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> <span class="hljs-built_in">require</span>.resolve(<span class="hljs-string">&#x27;.&#x27;</span>).indexOf(process.cwd()) <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
console.error <span class="hljs-string">&#x27;&#x27;&#x27;
To use --transpile, you must have @babel/core installed:
npm install --save-dev @babel/core
And you must save options to configure Babel in one of the places it looks to find its options.
See https://coffeescript.org/#transpilation
'''</span>
&#x27;&#x27;&#x27;</span>
<span class="hljs-keyword">else</span>
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'''
console.error <span class="hljs-string">&#x27;&#x27;&#x27;
To use --transpile with globally-installed CoffeeScript, you must have @babel/core installed globally:
npm install --global @babel/core
And you must save options to configure Babel in one of the places it looks to find its options, relative to the file being compiled or to the current folder.
See https://coffeescript.org/#transpilation
'''</span>
&#x27;&#x27;&#x27;</span>
process.exit <span class="hljs-number">1</span>
opts.transpile = {} <span class="hljs-keyword">unless</span> <span class="hljs-keyword">typeof</span> opts.transpile <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span></pre></div></div>
opts.transpile = {} <span class="hljs-keyword">unless</span> <span class="hljs-keyword">typeof</span> opts.transpile <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;object&#x27;</span></pre></div></div>
</li>
@@ -919,8 +923,8 @@ locally or globally.</p>
<li id="section-28">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-28">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-28">&#x00a7;</a>
</div>
<p>Pass a reference to Babel into the compiler, so that the transpile option
is available for the CLI. We need to do this so that tools like Webpack
@@ -937,8 +941,8 @@ require Babel.</p>
<li id="section-29">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-29">&#x00a7;</a>
</div>
<p>Babel searches for its options (a <code>.babelrc</code> file, a <code>.babelrc.js</code> file,
a <code>package.json</code> file with a <code>babel</code> key, etc.) relative to the path
@@ -948,7 +952,7 @@ along.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">unless</span> opts.transpile.filename
opts.transpile.filename = filename <span class="hljs-keyword">or</span> path.resolve(base <span class="hljs-keyword">or</span> process.cwd(), <span class="hljs-string">'&lt;anonymous&gt;'</span>)
opts.transpile.filename = filename <span class="hljs-keyword">or</span> path.resolve(base <span class="hljs-keyword">or</span> process.cwd(), <span class="hljs-string">&#x27;&lt;anonymous&gt;&#x27;</span>)
<span class="hljs-keyword">else</span>
opts.transpile = <span class="hljs-literal">no</span>
@@ -956,10 +960,11 @@ along.</p>
filename: filename
literate: opts.literate <span class="hljs-keyword">or</span> helpers.isLiterate(filename)
bare: opts.bare
header: opts.compile <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> opts[<span class="hljs-string">'no-header'</span>]
header: opts.compile <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> opts[<span class="hljs-string">&#x27;no-header&#x27;</span>]
transpile: opts.transpile
sourceMap: opts.map
inlineMap: opts[<span class="hljs-string">'inline-map'</span>]
inlineMap: opts[<span class="hljs-string">&#x27;inline-map&#x27;</span>]
ast: opts.ast
<span class="hljs-keyword">if</span> filename
<span class="hljs-keyword">if</span> base
@@ -968,15 +973,15 @@ along.</p>
jsDir = path.dirname jsPath
answer = helpers.merge answer, {
jsPath
sourceRoot: path.relative jsDir, cwd
sourceRoot: path.relative(jsDir, cwd) + path.sep
sourceFiles: [path.relative cwd, filename]
generatedFile: helpers.baseFileName(jsPath, <span class="hljs-literal">no</span>, useWinPathSep)
}
<span class="hljs-keyword">else</span>
answer = helpers.merge answer,
sourceRoot: <span class="hljs-string">""</span>
sourceRoot: <span class="hljs-string">&quot;&quot;</span>
sourceFiles: [helpers.baseFileName filename, <span class="hljs-literal">no</span>, useWinPathSep]
generatedFile: helpers.baseFileName(filename, <span class="hljs-literal">yes</span>, useWinPathSep) + <span class="hljs-string">".js"</span>
generatedFile: helpers.baseFileName(filename, <span class="hljs-literal">yes</span>, useWinPathSep) + <span class="hljs-string">&quot;.js&quot;</span>
answer</pre></div></div>
</li>
@@ -985,8 +990,8 @@ along.</p>
<li id="section-30">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-30">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-30">&#x00a7;</a>
</div>
<p>Start up a new Node.js instance with the arguments in <code>--nodejs</code> passed to
the <code>node</code> binary, preserving the other options.</p>
@@ -996,15 +1001,15 @@ the <code>node</code> binary, preserving the other options.</p>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">forkNode</span> = -&gt;</span>
nodeArgs = opts.nodejs.split <span class="hljs-regexp">/\s+/</span>
args = process.argv[<span class="hljs-number">1.</span>.]
args.splice args.indexOf(<span class="hljs-string">'--nodejs'</span>), <span class="hljs-number">2</span>
args.splice args.indexOf(<span class="hljs-string">&#x27;--nodejs&#x27;</span>), <span class="hljs-number">2</span>
p = spawn process.execPath, nodeArgs.concat(args),
cwd: process.cwd()
env: process.env
stdio: [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>]
<span class="hljs-keyword">for</span> signal <span class="hljs-keyword">in</span> [<span class="hljs-string">'SIGINT'</span>, <span class="hljs-string">'SIGTERM'</span>]
<span class="hljs-keyword">for</span> signal <span class="hljs-keyword">in</span> [<span class="hljs-string">&#x27;SIGINT&#x27;</span>, <span class="hljs-string">&#x27;SIGTERM&#x27;</span>]
process.<span class="hljs-literal">on</span> signal, <span class="hljs-keyword">do</span> (signal) -&gt;
-&gt; p.kill signal
p.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -&gt;</span> process.exit code</pre></div></div>
p.<span class="hljs-literal">on</span> <span class="hljs-string">&#x27;exit&#x27;</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -&gt;</span> process.exit code</pre></div></div>
</li>
@@ -1012,8 +1017,8 @@ the <code>node</code> binary, preserving the other options.</p>
<li id="section-31">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-31">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-31">&#x00a7;</a>
</div>
<p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
shown.</p>
@@ -1029,15 +1034,15 @@ shown.</p>
<li id="section-32">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-32">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-32">&#x00a7;</a>
</div>
<p>Print the <code>--version</code> message and exit.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">version</span> = -&gt;</span>
printLine <span class="hljs-string">"CoffeeScript version <span class="hljs-subst">#{CoffeeScript.VERSION}</span>"</span></pre></div></div>
printLine <span class="hljs-string">&quot;CoffeeScript version <span class="hljs-subst">#{CoffeeScript.VERSION}</span>&quot;</span></pre></div></div>
</li>

View File

@@ -213,7 +213,7 @@ ul.sections > li > div {
/*---------------------- Low resolutions (> 320px) ---------------------*/
@media only screen and (min-width: 320px) {
.pilwrap { display: none; }
.sswrap { display: none; }
ul.sections > li > div {
display: block;
@@ -330,12 +330,12 @@ ul.sections > li > div {
box-shadow: none;
}
.pilwrap {
.sswrap {
position: relative;
display: inline;
}
.pilcrow {
.ss {
font: 12px Arial;
text-decoration: none;
color: #454545;
@@ -345,14 +345,14 @@ ul.sections > li > div {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
}
.for-h1 .pilcrow {
.for-h1 .ss {
top: 47px;
}
.for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow {
.for-h2 .ss, .for-h3 .ss, .for-h4 .ss {
top: 35px;
}
ul.sections > li > div.annotation:hover .pilcrow {
ul.sections > li > div.annotation:hover .ss {
opacity: 1;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -112,8 +112,8 @@
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-1">&#x00a7;</a>
</div>
<p>This file contains the common helper functions that wed like to share among
the <strong>Lexer</strong>, <strong>Rewriter</strong>, and the <strong>Nodes</strong>. Merge objects, flatten
@@ -127,14 +127,14 @@ arrays, count characters, that sort of thing.</p>
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-2">&#x00a7;</a>
</div>
<p>Peek at the beginning of a given string to see if it matches a sequence.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.starts = <span class="hljs-function"><span class="hljs-params">(string, literal, start)</span> -&gt;</span>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.starts = <span class="hljs-function"><span class="hljs-params">(string, literal, start)</span> -&gt;</span>
literal <span class="hljs-keyword">is</span> string.substr start, literal.length</pre></div></div>
</li>
@@ -143,14 +143,14 @@ arrays, count characters, that sort of thing.</p>
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-3">&#x00a7;</a>
</div>
<p>Peek at the end of a given string to see if it matches a sequence.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.ends = <span class="hljs-function"><span class="hljs-params">(string, literal, back)</span> -&gt;</span>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.ends = <span class="hljs-function"><span class="hljs-params">(string, literal, back)</span> -&gt;</span>
len = literal.length
literal <span class="hljs-keyword">is</span> string.substr string.length - len - (back <span class="hljs-keyword">or</span> <span class="hljs-number">0</span>), len</pre></div></div>
@@ -160,14 +160,14 @@ arrays, count characters, that sort of thing.</p>
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-4">&#x00a7;</a>
</div>
<p>Repeat a string <code>n</code> times.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.repeat = repeat = <span class="hljs-function"><span class="hljs-params">(str, n)</span> -&gt;</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.repeat = repeat = <span class="hljs-function"><span class="hljs-params">(str, n)</span> -&gt;</span></pre></div></div>
</li>
@@ -175,14 +175,14 @@ arrays, count characters, that sort of thing.</p>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-5">&#x00a7;</a>
</div>
<p>Use clever algorithm to have O(log(n)) string concatenation operations.</p>
</div>
<div class="content"><div class='highlight'><pre> res = <span class="hljs-string">''</span>
<div class="content"><div class='highlight'><pre> res = <span class="hljs-string">&#x27;&#x27;</span>
<span class="hljs-keyword">while</span> n &gt; <span class="hljs-number">0</span>
res += str <span class="hljs-keyword">if</span> n &amp; <span class="hljs-number">1</span>
n &gt;&gt;&gt;= <span class="hljs-number">1</span>
@@ -195,14 +195,14 @@ arrays, count characters, that sort of thing.</p>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-6">&#x00a7;</a>
</div>
<p>Trim out all falsy values from an array.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.compact = <span class="hljs-function"><span class="hljs-params">(array)</span> -&gt;</span>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.compact = <span class="hljs-function"><span class="hljs-params">(array)</span> -&gt;</span>
item <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> array <span class="hljs-keyword">when</span> item</pre></div></div>
</li>
@@ -211,14 +211,14 @@ arrays, count characters, that sort of thing.</p>
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-7">&#x00a7;</a>
</div>
<p>Count the number of occurrences of a string in a string.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.count = <span class="hljs-function"><span class="hljs-params">(string, substr)</span> -&gt;</span>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.count = <span class="hljs-function"><span class="hljs-params">(string, substr)</span> -&gt;</span>
num = pos = <span class="hljs-number">0</span>
<span class="hljs-keyword">return</span> <span class="hljs-number">1</span>/<span class="hljs-number">0</span> <span class="hljs-keyword">unless</span> substr.length
num++ <span class="hljs-keyword">while</span> pos = <span class="hljs-number">1</span> + string.indexOf substr, pos
@@ -230,8 +230,8 @@ arrays, count characters, that sort of thing.</p>
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-8">&#x00a7;</a>
</div>
<p>Merge objects, returning a fresh copy with attributes from both sides.
Used every time <code>Base#compile</code> is called, to allow properties in the
@@ -239,7 +239,7 @@ options hash to propagate down the tree without polluting other branches.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.merge = <span class="hljs-function"><span class="hljs-params">(options, overrides)</span> -&gt;</span>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.merge = <span class="hljs-function"><span class="hljs-params">(options, overrides)</span> -&gt;</span>
extend (extend {}, options), overrides</pre></div></div>
</li>
@@ -248,14 +248,14 @@ options hash to propagate down the tree without polluting other branches.</p>
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-9">&#x00a7;</a>
</div>
<p>Extend a source object with the properties of another object (shallow copy).</p>
</div>
<div class="content"><div class='highlight'><pre>extend = exports.extend = <span class="hljs-function"><span class="hljs-params">(object, properties)</span> -&gt;</span>
<div class="content"><div class='highlight'><pre>extend = <span class="hljs-built_in">exports</span>.extend = <span class="hljs-function"><span class="hljs-params">(object, properties)</span> -&gt;</span>
<span class="hljs-keyword">for</span> key, val <span class="hljs-keyword">of</span> properties
object[key] = val
object</pre></div></div>
@@ -266,18 +266,18 @@ options hash to propagate down the tree without polluting other branches.</p>
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-10">&#x00a7;</a>
</div>
<p>Return a flattened version of an array.
Handy for getting a list of <code>children</code> from the nodes.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.flatten = flatten = <span class="hljs-function"><span class="hljs-params">(array)</span> -&gt;</span>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.flatten = flatten = <span class="hljs-function"><span class="hljs-params">(array)</span> -&gt;</span>
flattened = []
<span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> array
<span class="hljs-keyword">if</span> <span class="hljs-string">'[object Array]'</span> <span class="hljs-keyword">is</span> Object::toString.call element
<span class="hljs-keyword">if</span> <span class="hljs-string">&#x27;[object Array]&#x27;</span> <span class="hljs-keyword">is</span> Object::toString.call element
flattened = flattened.concat flatten element
<span class="hljs-keyword">else</span>
flattened.push element
@@ -289,15 +289,15 @@ Handy for getting a list of <code>children</code> from the nodes.</p>
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-11">&#x00a7;</a>
</div>
<p>Delete a key from an object, returning the value. Useful when a node is
looking for a particular method in an options hash.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.del = <span class="hljs-function"><span class="hljs-params">(obj, key)</span> -&gt;</span>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.del = <span class="hljs-function"><span class="hljs-params">(obj, key)</span> -&gt;</span>
val = obj[key]
<span class="hljs-keyword">delete</span> obj[key]
val</pre></div></div>
@@ -308,15 +308,15 @@ looking for a particular method in an options hash.</p>
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-12">&#x00a7;</a>
</div>
<p>Typical Array::some</p>
</div>
<div class="content"><div class='highlight'><pre>exports.some = Array::some ? (fn) -&gt;
<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span> <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> <span class="hljs-keyword">this</span> <span class="hljs-keyword">when</span> fn e
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.some = Array::some ? (fn) -&gt;
<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span> <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> this <span class="hljs-keyword">when</span> fn e
<span class="hljs-literal">false</span></pre></div></div>
</li>
@@ -325,8 +325,8 @@ looking for a particular method in an options hash.</p>
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-13">&#x00a7;</a>
</div>
<p>Helper function for extracting code from Literate CoffeeScript by stripping
out all non-code blocks, producing a string of CoffeeScript code that can
@@ -334,7 +334,7 @@ be compiled “normally.”</p>
</div>
<div class="content"><div class='highlight'><pre>exports.invertLiterate = <span class="hljs-function"><span class="hljs-params">(code)</span> -&gt;</span>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.invertLiterate = <span class="hljs-function"><span class="hljs-params">(code)</span> -&gt;</span>
out = []
blankLine = <span class="hljs-regexp">/^\s*$/</span>
indented = <span class="hljs-regexp">/^[\t ]/</span>
@@ -347,19 +347,19 @@ be compiled “normally.”</p>
[\ \t] <span class="hljs-comment"># followed by a space or a tab.</span>
///</span>
insideComment = <span class="hljs-literal">no</span>
<span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> code.split(<span class="hljs-string">'\n'</span>)
<span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> code.split(<span class="hljs-string">&#x27;\n&#x27;</span>)
<span class="hljs-keyword">if</span> blankLine.test(line)
insideComment = <span class="hljs-literal">no</span>
out.push line
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> insideComment <span class="hljs-keyword">or</span> listItemStart.test(line)
insideComment = <span class="hljs-literal">yes</span>
out.push <span class="hljs-string">"# <span class="hljs-subst">#{line}</span>"</span>
out.push <span class="hljs-string">&quot;# <span class="hljs-subst">#{line}</span>&quot;</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> insideComment <span class="hljs-keyword">and</span> indented.test(line)
out.push line
<span class="hljs-keyword">else</span>
insideComment = <span class="hljs-literal">yes</span>
out.push <span class="hljs-string">"# <span class="hljs-subst">#{line}</span>"</span>
out.join <span class="hljs-string">'\n'</span></pre></div></div>
out.push <span class="hljs-string">&quot;# <span class="hljs-subst">#{line}</span>&quot;</span>
out.join <span class="hljs-string">&#x27;\n&#x27;</span></pre></div></div>
</li>
@@ -367,8 +367,8 @@ be compiled “normally.”</p>
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-14">&#x00a7;</a>
</div>
<p>Merge two jison-style location data objects together.
If <code>last</code> is not provided, this will simply return <code>first</code>.</p>
@@ -383,9 +383,12 @@ If <code>last</code> is not provided, this will simply return <code>first</code>
first_column: first.first_column
last_line: last.last_line
last_column: last.last_column
<span class="hljs-function">
<span class="hljs-title">buildLocationHash</span> = <span class="hljs-params">(loc)</span> -&gt;</span>
<span class="hljs-string">"<span class="hljs-subst">#{loc.first_line}</span>x<span class="hljs-subst">#{loc.first_column}</span>-<span class="hljs-subst">#{loc.last_line}</span>x<span class="hljs-subst">#{loc.last_column}</span>"</span></pre></div></div>
last_line_exclusive: last.last_line_exclusive
last_column_exclusive: last.last_column_exclusive
range: [
first.range[<span class="hljs-number">0</span>]
last.range[<span class="hljs-number">1</span>]
]</pre></div></div>
</li>
@@ -393,18 +396,22 @@ If <code>last</code> is not provided, this will simply return <code>first</code>
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-15">&#x00a7;</a>
</div>
<p>Build a dictionary of extra token properties organized by tokens locations
used as lookup hashes.</p>
<p>Build a list of all comments attached to tokens.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">buildTokenDataDictionary</span> = <span class="hljs-params">(parserState)</span> -&gt;</span>
tokenData = {}
<span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> parserState.parser.tokens <span class="hljs-keyword">when</span> token.comments
tokenHash = buildLocationHash token[<span class="hljs-number">2</span>]</pre></div></div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.extractAllCommentTokens = <span class="hljs-function"><span class="hljs-params">(tokens)</span> -&gt;</span>
allCommentsObj = {}
<span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token.comments
<span class="hljs-keyword">for</span> comment <span class="hljs-keyword">in</span> token.comments
commentKey = comment.locationData.range[<span class="hljs-number">0</span>]
allCommentsObj[commentKey] = comment
sortedKeys = <span class="hljs-built_in">Object</span>.keys(allCommentsObj).sort (a, b) -&gt; a - b
<span class="hljs-keyword">for</span> key <span class="hljs-keyword">in</span> sortedKeys
allCommentsObj[key]</pre></div></div>
</li>
@@ -412,8 +419,46 @@ used as lookup hashes.</p>
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-16">&#x00a7;</a>
</div>
<p>Get a lookup hash for a token based on its location data.
Multiple tokens might have the same location hash, but using exclusive
location data distinguishes e.g. zero-length generated tokens from
actual source tokens.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">buildLocationHash</span> = <span class="hljs-params">(loc)</span> -&gt;</span>
<span class="hljs-string">&quot;<span class="hljs-subst">#{loc.range[<span class="hljs-number">0</span>]}</span>-<span class="hljs-subst">#{loc.range[<span class="hljs-number">1</span>]}</span>&quot;</span></pre></div></div>
</li>
<li id="section-17">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-17">&#x00a7;</a>
</div>
<p>Build a dictionary of extra token properties organized by tokens locations
used as lookup hashes.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.buildTokenDataDictionary = buildTokenDataDictionary = <span class="hljs-function"><span class="hljs-params">(tokens)</span> -&gt;</span>
tokenData = {}
<span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token.comments
tokenHash = buildLocationHash token[<span class="hljs-number">2</span>]</pre></div></div>
</li>
<li id="section-18">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-18">&#x00a7;</a>
</div>
<p>Multiple tokens might have the same location hash, such as the generated
<code>JS</code> tokens added at the start or end of the token stream to hold
@@ -427,11 +472,11 @@ comments that start or end a file.</p>
</li>
<li id="section-17">
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-19">&#x00a7;</a>
</div>
<p>For “overlapping” tokens, that is tokens with the same location data
and therefore matching <code>tokenHash</code>es, merge the comments from both/all
@@ -446,11 +491,11 @@ they will get sorted out later.</p>
</li>
<li id="section-18">
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-20">&#x00a7;</a>
</div>
<p>This returns a function which takes an object as a parameter, and if that
object is an AST node, updates that objects locationData.
@@ -458,74 +503,27 @@ The object is returned either way.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.addDataToNode = <span class="hljs-function"><span class="hljs-params">(parserState, first, last)</span> -&gt;</span>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.addDataToNode = <span class="hljs-function"><span class="hljs-params">(parserState, firstLocationData, firstValue, lastLocationData, lastValue, forceUpdateLocation = <span class="hljs-literal">yes</span>)</span> -&gt;</span>
(obj) -&gt;</pre></div></div>
</li>
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
</div>
<p>Add location data.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> obj?.updateLocationDataIfMissing? <span class="hljs-keyword">and</span> first?
obj.updateLocationDataIfMissing buildLocationData(first, last)</pre></div></div>
</li>
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
</div>
<p>Add comments, building the dictionary of token data if it hasnt been
built yet.</p>
</div>
<div class="content"><div class='highlight'><pre> parserState.tokenData ?= buildTokenDataDictionary parserState
<span class="hljs-keyword">if</span> obj.locationData?
objHash = buildLocationHash obj.locationData
<span class="hljs-keyword">if</span> parserState.tokenData[objHash]?.comments?
attachCommentsToNode parserState.tokenData[objHash].comments, obj
obj
exports.attachCommentsToNode = attachCommentsToNode = <span class="hljs-function"><span class="hljs-params">(comments, node)</span> -&gt;</span>
<span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> comments? <span class="hljs-keyword">or</span> comments.length <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
node.comments ?= []
node.comments.push comments...</pre></div></div>
</li>
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-21">&#x00a7;</a>
</div>
<p>Convert jison location data to a string.
<code>obj</code> can be a token, or a locationData.</p>
<p>Add location data.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.locationDataToString = <span class="hljs-function"><span class="hljs-params">(obj)</span> -&gt;</span>
<span class="hljs-keyword">if</span> (<span class="hljs-string">"2"</span> <span class="hljs-keyword">of</span> obj) <span class="hljs-keyword">and</span> (<span class="hljs-string">"first_line"</span> <span class="hljs-keyword">of</span> obj[<span class="hljs-number">2</span>]) <span class="hljs-keyword">then</span> locationData = obj[<span class="hljs-number">2</span>]
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-string">"first_line"</span> <span class="hljs-keyword">of</span> obj <span class="hljs-keyword">then</span> locationData = obj
<span class="hljs-keyword">if</span> locationData
<span class="hljs-string">"<span class="hljs-subst">#{locationData.first_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{locationData.first_column + <span class="hljs-number">1</span>}</span>-"</span> +
<span class="hljs-string">"<span class="hljs-subst">#{locationData.last_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{locationData.last_column + <span class="hljs-number">1</span>}</span>"</span>
<span class="hljs-keyword">else</span>
<span class="hljs-string">"No location data"</span></pre></div></div>
<div class="content"><div class='highlight'><pre> locationData = buildLocationData(firstValue?.locationData ? firstLocationData, lastValue?.locationData ? lastLocationData)
<span class="hljs-keyword">if</span> obj?.updateLocationDataIfMissing? <span class="hljs-keyword">and</span> firstLocationData?
obj.updateLocationDataIfMissing locationData, forceUpdateLocation
<span class="hljs-keyword">else</span>
obj.locationData = locationData</pre></div></div>
</li>
@@ -533,22 +531,25 @@ exports.attachCommentsToNode = attachCommentsToNode = <span class="hljs-function
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-22">&#x00a7;</a>
</div>
<p>A <code>.coffee.md</code> compatible version of <code>basename</code>, that returns the file sans-extension.</p>
<p>Add comments, building the dictionary of token data if it hasnt been
built yet.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.baseFileName = <span class="hljs-function"><span class="hljs-params">(file, stripExt = <span class="hljs-literal">no</span>, useWinPathSep = <span class="hljs-literal">no</span>)</span> -&gt;</span>
pathSep = <span class="hljs-keyword">if</span> useWinPathSep <span class="hljs-keyword">then</span> <span class="hljs-regexp">/\\|\//</span> <span class="hljs-keyword">else</span> <span class="hljs-regexp">/\//</span>
parts = file.split(pathSep)
file = parts[parts.length - <span class="hljs-number">1</span>]
<span class="hljs-keyword">return</span> file <span class="hljs-keyword">unless</span> stripExt <span class="hljs-keyword">and</span> file.indexOf(<span class="hljs-string">'.'</span>) &gt;= <span class="hljs-number">0</span>
parts = file.split(<span class="hljs-string">'.'</span>)
parts.pop()
parts.pop() <span class="hljs-keyword">if</span> parts[parts.length - <span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'coffee'</span> <span class="hljs-keyword">and</span> parts.length &gt; <span class="hljs-number">1</span>
parts.join(<span class="hljs-string">'.'</span>)</pre></div></div>
<div class="content"><div class='highlight'><pre> parserState.tokenData ?= buildTokenDataDictionary parserState.parser.tokens
<span class="hljs-keyword">if</span> obj.locationData?
objHash = buildLocationHash obj.locationData
<span class="hljs-keyword">if</span> parserState.tokenData[objHash]?.comments?
attachCommentsToNode parserState.tokenData[objHash].comments, obj
obj
<span class="hljs-built_in">exports</span>.attachCommentsToNode = attachCommentsToNode = <span class="hljs-function"><span class="hljs-params">(comments, node)</span> -&gt;</span>
<span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> comments? <span class="hljs-keyword">or</span> comments.length <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
node.comments ?= []
node.comments.push comments...</pre></div></div>
</li>
@@ -556,14 +557,23 @@ exports.attachCommentsToNode = attachCommentsToNode = <span class="hljs-function
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-23">&#x00a7;</a>
</div>
<p>Determine if a filename represents a CoffeeScript file.</p>
<p>Convert jison location data to a string.
<code>obj</code> can be a token, or a locationData.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.isCoffee = <span class="hljs-function"><span class="hljs-params">(file)</span> -&gt;</span> <span class="hljs-regexp">/\.((lit)?coffee|coffee\.md)$/</span>.test file</pre></div></div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.locationDataToString = <span class="hljs-function"><span class="hljs-params">(obj)</span> -&gt;</span>
<span class="hljs-keyword">if</span> (<span class="hljs-string">&quot;2&quot;</span> <span class="hljs-keyword">of</span> obj) <span class="hljs-keyword">and</span> (<span class="hljs-string">&quot;first_line&quot;</span> <span class="hljs-keyword">of</span> obj[<span class="hljs-number">2</span>]) <span class="hljs-keyword">then</span> locationData = obj[<span class="hljs-number">2</span>]
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-string">&quot;first_line&quot;</span> <span class="hljs-keyword">of</span> obj <span class="hljs-keyword">then</span> locationData = obj
<span class="hljs-keyword">if</span> locationData
<span class="hljs-string">&quot;<span class="hljs-subst">#{locationData.first_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{locationData.first_column + <span class="hljs-number">1</span>}</span>-&quot;</span> +
<span class="hljs-string">&quot;<span class="hljs-subst">#{locationData.last_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{locationData.last_column + <span class="hljs-number">1</span>}</span>&quot;</span>
<span class="hljs-keyword">else</span>
<span class="hljs-string">&quot;No location data&quot;</span></pre></div></div>
</li>
@@ -571,14 +581,18 @@ exports.attachCommentsToNode = attachCommentsToNode = <span class="hljs-function
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-24">&#x00a7;</a>
</div>
<p>Determine if a filename represents a Literate CoffeeScript file.</p>
<p>Generate a unique anonymous file name so we can distinguish source map cache
entries for any number of anonymous scripts.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.isLiterate = <span class="hljs-function"><span class="hljs-params">(file)</span> -&gt;</span> <span class="hljs-regexp">/\.(litcoffee|coffee\.md)$/</span>.test file</pre></div></div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.anonymousFileName = <span class="hljs-keyword">do</span> -&gt;
n = <span class="hljs-number">0</span>
-&gt;
<span class="hljs-string">&quot;&lt;anonymous-<span class="hljs-subst">#{n++}</span>&gt;&quot;</span></pre></div></div>
</li>
@@ -586,8 +600,61 @@ exports.attachCommentsToNode = attachCommentsToNode = <span class="hljs-function
<li id="section-25">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-25">&#x00a7;</a>
</div>
<p>A <code>.coffee.md</code> compatible version of <code>basename</code>, that returns the file sans-extension.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.baseFileName = <span class="hljs-function"><span class="hljs-params">(file, stripExt = <span class="hljs-literal">no</span>, useWinPathSep = <span class="hljs-literal">no</span>)</span> -&gt;</span>
pathSep = <span class="hljs-keyword">if</span> useWinPathSep <span class="hljs-keyword">then</span> <span class="hljs-regexp">/\\|\//</span> <span class="hljs-keyword">else</span> <span class="hljs-regexp">/\//</span>
parts = file.split(pathSep)
file = parts[parts.length - <span class="hljs-number">1</span>]
<span class="hljs-keyword">return</span> file <span class="hljs-keyword">unless</span> stripExt <span class="hljs-keyword">and</span> file.indexOf(<span class="hljs-string">&#x27;.&#x27;</span>) &gt;= <span class="hljs-number">0</span>
parts = file.split(<span class="hljs-string">&#x27;.&#x27;</span>)
parts.pop()
parts.pop() <span class="hljs-keyword">if</span> parts[parts.length - <span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;coffee&#x27;</span> <span class="hljs-keyword">and</span> parts.length &gt; <span class="hljs-number">1</span>
parts.join(<span class="hljs-string">&#x27;.&#x27;</span>)</pre></div></div>
</li>
<li id="section-26">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-26">&#x00a7;</a>
</div>
<p>Determine if a filename represents a CoffeeScript file.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.isCoffee = <span class="hljs-function"><span class="hljs-params">(file)</span> -&gt;</span> <span class="hljs-regexp">/\.((lit)?coffee|coffee\.md)$/</span>.test file</pre></div></div>
</li>
<li id="section-27">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-27">&#x00a7;</a>
</div>
<p>Determine if a filename represents a Literate CoffeeScript file.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.isLiterate = <span class="hljs-function"><span class="hljs-params">(file)</span> -&gt;</span> <span class="hljs-regexp">/\.(litcoffee|coffee\.md)$/</span>.test file</pre></div></div>
</li>
<li id="section-28">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-28">&#x00a7;</a>
</div>
<p>Throws a SyntaxError from a given location.
The errors <code>toString</code> will return an error message following the “standard”
@@ -596,19 +663,19 @@ marker showing where the error is.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.throwSyntaxError = <span class="hljs-function"><span class="hljs-params">(message, location)</span> -&gt;</span>
error = <span class="hljs-keyword">new</span> SyntaxError message
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.throwSyntaxError = <span class="hljs-function"><span class="hljs-params">(message, location)</span> -&gt;</span>
error = <span class="hljs-keyword">new</span> <span class="hljs-built_in">SyntaxError</span> message
error.location = location
error.toString = syntaxErrorToString</pre></div></div>
</li>
<li id="section-26">
<li id="section-29">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-29">&#x00a7;</a>
</div>
<p>Instead of showing the compilers stacktrace, show our custom error message
(this is useful when the error bubbles up in Node.js applications that
@@ -623,27 +690,27 @@ compile CoffeeScript for example).</p>
</li>
<li id="section-27">
<li id="section-30">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-30">&#x00a7;</a>
</div>
<p>Update a compiler SyntaxError with source code information if it didnt have
it already.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.updateSyntaxError = <span class="hljs-function"><span class="hljs-params">(error, code, filename)</span> -&gt;</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.updateSyntaxError = <span class="hljs-function"><span class="hljs-params">(error, code, filename)</span> -&gt;</span></pre></div></div>
</li>
<li id="section-28">
<li id="section-31">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-28">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-31">&#x00a7;</a>
</div>
<p>Avoid screwing up the <code>stack</code> property of other errors (i.e. possible bugs).</p>
@@ -662,34 +729,38 @@ it already.</p>
last_line ?= first_line
last_column ?= first_column
filename = @filename <span class="hljs-keyword">or</span> <span class="hljs-string">'[stdin]'</span>
codeLine = @code.split(<span class="hljs-string">'\n'</span>)[first_line]
<span class="hljs-keyword">if</span> @filename?.startsWith <span class="hljs-string">&#x27;&lt;anonymous&#x27;</span>
filename = <span class="hljs-string">&#x27;[stdin]&#x27;</span>
<span class="hljs-keyword">else</span>
filename = @filename <span class="hljs-keyword">or</span> <span class="hljs-string">&#x27;[stdin]&#x27;</span>
codeLine = @code.split(<span class="hljs-string">&#x27;\n&#x27;</span>)[first_line]
start = first_column</pre></div></div>
</li>
<li id="section-29">
<li id="section-32">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-32">&#x00a7;</a>
</div>
<p>Show only the first line on multi-line errors.</p>
</div>
<div class="content"><div class='highlight'><pre> end = <span class="hljs-keyword">if</span> first_line <span class="hljs-keyword">is</span> last_line <span class="hljs-keyword">then</span> last_column + <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> codeLine.length
marker = codeLine[...start].replace(<span class="hljs-regexp">/[^\s]/g</span>, <span class="hljs-string">' '</span>) + repeat(<span class="hljs-string">'^'</span>, end - start)</pre></div></div>
marker = codeLine[...start].replace(<span class="hljs-regexp">/[^\s]/g</span>, <span class="hljs-string">&#x27; &#x27;</span>) + repeat(<span class="hljs-string">&#x27;^&#x27;</span>, end - start)</pre></div></div>
</li>
<li id="section-30">
<li id="section-33">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-30">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-33">&#x00a7;</a>
</div>
<p>Check to see if were running on a color-enabled TTY.</p>
@@ -699,23 +770,99 @@ it already.</p>
colorsEnabled = process.stdout?.isTTY <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> process.env?.NODE_DISABLE_COLORS
<span class="hljs-keyword">if</span> @colorful ? colorsEnabled
<span class="hljs-function"> <span class="hljs-title">colorize</span> = <span class="hljs-params">(str)</span> -&gt;</span> <span class="hljs-string">"\x1B[1;31m<span class="hljs-subst">#{str}</span>\x1B[0m"</span>
<span class="hljs-function"> <span class="hljs-title">colorize</span> = <span class="hljs-params">(str)</span> -&gt;</span> <span class="hljs-string">&quot;\x1B[1;31m<span class="hljs-subst">#{str}</span>\x1B[0m&quot;</span>
codeLine = codeLine[...start] + colorize(codeLine[start...end]) + codeLine[end..]
marker = colorize marker
<span class="hljs-string">"""
<span class="hljs-string">&quot;&quot;&quot;
<span class="hljs-subst">#{filename}</span>:<span class="hljs-subst">#{first_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{first_column + <span class="hljs-number">1</span>}</span>: error: <span class="hljs-subst">#{@message}</span>
<span class="hljs-subst">#{codeLine}</span>
<span class="hljs-subst">#{marker}</span>
"""</span>
&quot;&quot;&quot;</span>
exports.nameWhitespaceCharacter = <span class="hljs-function"><span class="hljs-params">(string)</span> -&gt;</span>
<span class="hljs-built_in">exports</span>.nameWhitespaceCharacter = <span class="hljs-function"><span class="hljs-params">(string)</span> -&gt;</span>
<span class="hljs-keyword">switch</span> string
<span class="hljs-keyword">when</span> <span class="hljs-string">' '</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'space'</span>
<span class="hljs-keyword">when</span> <span class="hljs-string">'\n'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'newline'</span>
<span class="hljs-keyword">when</span> <span class="hljs-string">'\r'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'carriage return'</span>
<span class="hljs-keyword">when</span> <span class="hljs-string">'\t'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'tab'</span>
<span class="hljs-keyword">else</span> string</pre></div></div>
<span class="hljs-keyword">when</span> <span class="hljs-string">&#x27; &#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-string">&#x27;space&#x27;</span>
<span class="hljs-keyword">when</span> <span class="hljs-string">&#x27;\n&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-string">&#x27;newline&#x27;</span>
<span class="hljs-keyword">when</span> <span class="hljs-string">&#x27;\r&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-string">&#x27;carriage return&#x27;</span>
<span class="hljs-keyword">when</span> <span class="hljs-string">&#x27;\t&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-string">&#x27;tab&#x27;</span>
<span class="hljs-keyword">else</span> string
<span class="hljs-built_in">exports</span>.parseNumber = <span class="hljs-function"><span class="hljs-params">(string)</span> -&gt;</span>
<span class="hljs-keyword">return</span> <span class="hljs-literal">NaN</span> <span class="hljs-keyword">unless</span> string?
base = <span class="hljs-keyword">switch</span> string.charAt <span class="hljs-number">1</span>
<span class="hljs-keyword">when</span> <span class="hljs-string">&#x27;b&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-number">2</span>
<span class="hljs-keyword">when</span> <span class="hljs-string">&#x27;o&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-number">8</span>
<span class="hljs-keyword">when</span> <span class="hljs-string">&#x27;x&#x27;</span> <span class="hljs-keyword">then</span> <span class="hljs-number">16</span>
<span class="hljs-keyword">else</span> <span class="hljs-literal">null</span>
<span class="hljs-keyword">if</span> base?
<span class="hljs-built_in">parseInt</span> string[<span class="hljs-number">2.</span>.].replace(<span class="hljs-regexp">/_/g</span>, <span class="hljs-string">&#x27;&#x27;</span>), base
<span class="hljs-keyword">else</span>
<span class="hljs-built_in">parseFloat</span> string.replace(<span class="hljs-regexp">/_/g</span>, <span class="hljs-string">&#x27;&#x27;</span>)
<span class="hljs-built_in">exports</span>.isFunction = <span class="hljs-function"><span class="hljs-params">(obj)</span> -&gt;</span> Object::toString.call(obj) <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;[object Function]&#x27;</span>
<span class="hljs-built_in">exports</span>.isNumber = isNumber = <span class="hljs-function"><span class="hljs-params">(obj)</span> -&gt;</span> Object::toString.call(obj) <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;[object Number]&#x27;</span>
<span class="hljs-built_in">exports</span>.isString = isString = <span class="hljs-function"><span class="hljs-params">(obj)</span> -&gt;</span> Object::toString.call(obj) <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;[object String]&#x27;</span>
<span class="hljs-built_in">exports</span>.isBoolean = isBoolean = <span class="hljs-function"><span class="hljs-params">(obj)</span> -&gt;</span> obj <span class="hljs-keyword">is</span> <span class="hljs-literal">yes</span> <span class="hljs-keyword">or</span> obj <span class="hljs-keyword">is</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">or</span> Object::toString.call(obj) <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;[object Boolean]&#x27;</span>
<span class="hljs-built_in">exports</span>.isPlainObject = <span class="hljs-function"><span class="hljs-params">(obj)</span> -&gt;</span> <span class="hljs-keyword">typeof</span> obj <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;object&#x27;</span> <span class="hljs-keyword">and</span> !!obj <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> <span class="hljs-built_in">Array</span>.isArray(obj) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> isNumber(obj) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> isString(obj) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> isBoolean(obj)
<span class="hljs-function">
<span class="hljs-title">unicodeCodePointToUnicodeEscapes</span> = <span class="hljs-params">(codePoint)</span> -&gt;</span>
<span class="hljs-function"> <span class="hljs-title">toUnicodeEscape</span> = <span class="hljs-params">(val)</span> -&gt;</span>
str = val.toString <span class="hljs-number">16</span>
<span class="hljs-string">&quot;\\u<span class="hljs-subst">#{repeat <span class="hljs-string">&#x27;0&#x27;</span>, <span class="hljs-number">4</span> - str.length}</span><span class="hljs-subst">#{str}</span>&quot;</span>
<span class="hljs-keyword">return</span> toUnicodeEscape(codePoint) <span class="hljs-keyword">if</span> codePoint &lt; <span class="hljs-number">0x10000</span></pre></div></div>
</li>
<li id="section-34">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-34">&#x00a7;</a>
</div>
<p>surrogate pair</p>
</div>
<div class="content"><div class='highlight'><pre> high = <span class="hljs-built_in">Math</span>.floor((codePoint - <span class="hljs-number">0x10000</span>) / <span class="hljs-number">0x400</span>) + <span class="hljs-number">0xD800</span>
low = (codePoint - <span class="hljs-number">0x10000</span>) % <span class="hljs-number">0x400</span> + <span class="hljs-number">0xDC00</span>
<span class="hljs-string">&quot;<span class="hljs-subst">#{toUnicodeEscape(high)}</span><span class="hljs-subst">#{toUnicodeEscape(low)}</span>&quot;</span></pre></div></div>
</li>
<li id="section-35">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-35">&#x00a7;</a>
</div>
<p>Replace <code>\u{...}</code> with <code>\uxxxx[\uxxxx]</code> in regexes without <code>u</code> flag</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.replaceUnicodeCodePointEscapes = <span class="hljs-function"><span class="hljs-params">(str, {flags, error, delimiter = <span class="hljs-string">&#x27;&#x27;</span>} = {})</span> -&gt;</span>
shouldReplace = flags? <span class="hljs-keyword">and</span> <span class="hljs-string">&#x27;u&#x27;</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> flags
str.replace UNICODE_CODE_POINT_ESCAPE, <span class="hljs-function"><span class="hljs-params">(match, escapedBackslash, codePointHex, offset)</span> -&gt;</span>
<span class="hljs-keyword">return</span> escapedBackslash <span class="hljs-keyword">if</span> escapedBackslash
codePointDecimal = <span class="hljs-built_in">parseInt</span> codePointHex, <span class="hljs-number">16</span>
<span class="hljs-keyword">if</span> codePointDecimal &gt; <span class="hljs-number">0x10ffff</span>
error <span class="hljs-string">&quot;unicode code point escapes greater than \\u{10ffff} are not allowed&quot;</span>,
offset: offset + delimiter.length
length: codePointHex.length + <span class="hljs-number">4</span>
<span class="hljs-keyword">return</span> match <span class="hljs-keyword">unless</span> shouldReplace
unicodeCodePointToUnicodeEscapes codePointDecimal
UNICODE_CODE_POINT_ESCAPE = <span class="hljs-regexp">///
( \\\\ ) <span class="hljs-comment"># Make sure the escape isnt escaped.</span>
|
\\u\{ ( [\da-fA-F]+ ) \}
///</span>g</pre></div></div>
</li>

View File

@@ -112,26 +112,26 @@
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-1">&#x00a7;</a>
</div>
<p>Node.js Implementation</p>
</div>
<div class="content"><div class='highlight'><pre>CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./coffeescript'</span>
fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
vm = <span class="hljs-built_in">require</span> <span class="hljs-string">'vm'</span>
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
<div class="content"><div class='highlight'><pre>CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./coffeescript&#x27;</span>
fs = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;fs&#x27;</span>
vm = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;vm&#x27;</span>
path = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;path&#x27;</span>
helpers = CoffeeScript.helpers
CoffeeScript.transpile = <span class="hljs-function"><span class="hljs-params">(js, options)</span> -&gt;</span>
<span class="hljs-keyword">try</span>
babel = <span class="hljs-built_in">require</span> <span class="hljs-string">'@babel/core'</span>
babel = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;@babel/core&#x27;</span>
<span class="hljs-keyword">catch</span>
<span class="hljs-keyword">try</span>
babel = <span class="hljs-built_in">require</span> <span class="hljs-string">'babel-core'</span>
babel = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;babel-core&#x27;</span>
<span class="hljs-keyword">catch</span></pre></div></div>
</li>
@@ -140,15 +140,15 @@ CoffeeScript.transpile = <span class="hljs-function"><span class="hljs-params">(
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-2">&#x00a7;</a>
</div>
<p>This error is only for Node, as CLI users will see a different error
earlier if they dont have Babel installed.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">'To use the transpile option, you must have the \'@babel/core\' module installed'</span>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">&#x27;To use the transpile option, you must have the \&#x27;@babel/core\&#x27; module installed&#x27;</span>
babel.transform js, options</pre></div></div>
</li>
@@ -157,8 +157,8 @@ earlier if they dont have Babel installed.</p>
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-3">&#x00a7;</a>
</div>
<p>The <code>compile</code> method shared by the CLI, Node and browser APIs.</p>
@@ -172,8 +172,8 @@ earlier if they dont have Babel installed.</p>
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-4">&#x00a7;</a>
</div>
<p>The <code>compile</code> method particular to the Node API.</p>
@@ -187,8 +187,8 @@ earlier if they dont have Babel installed.</p>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-5">&#x00a7;</a>
</div>
<p>Pass a reference to Babel into the compiler, so that the transpile option
is available in the Node API. We need to do this so that tools like Webpack
@@ -207,8 +207,8 @@ require Babel.</p>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-6">&#x00a7;</a>
</div>
<p>Compile and execute a string of CoffeeScript (on the server), correctly
setting <code>__filename</code>, <code>__dirname</code>, and relative <code>require()</code>.</p>
@@ -224,15 +224,15 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-7">&#x00a7;</a>
</div>
<p>Set the filename.</p>
</div>
<div class="content"><div class='highlight'><pre> mainModule.filename = process.argv[<span class="hljs-number">1</span>] =
<span class="hljs-keyword">if</span> options.filename <span class="hljs-keyword">then</span> fs.realpathSync(options.filename) <span class="hljs-keyword">else</span> <span class="hljs-string">'&lt;anonymous&gt;'</span></pre></div></div>
<span class="hljs-keyword">if</span> options.filename <span class="hljs-keyword">then</span> fs.realpathSync(options.filename) <span class="hljs-keyword">else</span> helpers.anonymousFileName()</pre></div></div>
</li>
@@ -240,8 +240,8 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-8">&#x00a7;</a>
</div>
<p>Clear the module cache.</p>
@@ -255,8 +255,8 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-9">&#x00a7;</a>
</div>
<p>Assign paths for node_modules loading</p>
@@ -265,8 +265,8 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
<div class="content"><div class='highlight'><pre> dir = <span class="hljs-keyword">if</span> options.filename?
path.dirname fs.realpathSync options.filename
<span class="hljs-keyword">else</span>
fs.realpathSync <span class="hljs-string">'.'</span>
mainModule.paths = <span class="hljs-built_in">require</span>(<span class="hljs-string">'module'</span>)._nodeModulePaths dir</pre></div></div>
fs.realpathSync <span class="hljs-string">&#x27;.&#x27;</span>
mainModule.paths = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;module&#x27;</span>)._nodeModulePaths dir</pre></div></div>
</li>
@@ -274,14 +274,17 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-10">&#x00a7;</a>
</div>
<p>Save the options for compiling child imports.</p>
</div>
<div class="content"><div class='highlight'><pre> mainModule.options = options</pre></div></div>
<div class="content"><div class='highlight'><pre> mainModule.options = options
options.filename = mainModule.filename
options.inlineMap = <span class="hljs-literal">true</span></pre></div></div>
</li>
@@ -289,16 +292,15 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-11">&#x00a7;</a>
</div>
<p>Compile.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> helpers.isCoffee(mainModule.filename) <span class="hljs-keyword">or</span> <span class="hljs-built_in">require</span>.extensions
answer = CoffeeScript.compile code, options
code = answer.js ? answer
<div class="content"><div class='highlight'><pre> answer = CoffeeScript.compile code, options
code = answer.js ? answer
mainModule._compile code, mainModule.filename</pre></div></div>
@@ -308,15 +310,15 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-12">&#x00a7;</a>
</div>
<p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
The CoffeeScript REPL uses this to run the input.</p>
</div>
<div class="content"><div class='highlight'><pre>CoffeeScript.eval = <span class="hljs-function"><span class="hljs-params">(code, options = {})</span> -&gt;</span>
<div class="content"><div class='highlight'><pre>CoffeeScript.<span class="hljs-built_in">eval</span> = <span class="hljs-function"><span class="hljs-params">(code, options = {})</span> -&gt;</span>
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> code = code.trim()
createContext = vm.Script.createContext ? vm.createContext
@@ -330,10 +332,10 @@ The CoffeeScript REPL uses this to run the input.</p>
<span class="hljs-keyword">else</span>
sandbox = createContext()
sandbox[k] = v <span class="hljs-keyword">for</span> own k, v <span class="hljs-keyword">of</span> options.sandbox
sandbox.<span class="hljs-built_in">global</span> = sandbox.root = sandbox.GLOBAL = sandbox
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox
<span class="hljs-keyword">else</span>
sandbox = <span class="hljs-built_in">global</span>
sandbox.__filename = options.filename || <span class="hljs-string">'eval'</span>
sandbox = global
sandbox.__filename = options.filename || <span class="hljs-string">&#x27;eval&#x27;</span>
sandbox.__dirname = path.dirname sandbox.__filename</pre></div></div>
</li>
@@ -342,19 +344,19 @@ The CoffeeScript REPL uses this to run the input.</p>
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-13">&#x00a7;</a>
</div>
<p>define module/require only if they chose not to specify their own</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">unless</span> sandbox <span class="hljs-keyword">isnt</span> <span class="hljs-built_in">global</span> <span class="hljs-keyword">or</span> sandbox.<span class="hljs-built_in">module</span> <span class="hljs-keyword">or</span> sandbox.<span class="hljs-built_in">require</span>
Module = <span class="hljs-built_in">require</span> <span class="hljs-string">'module'</span>
sandbox.<span class="hljs-built_in">module</span> = _module = <span class="hljs-keyword">new</span> Module(options.modulename || <span class="hljs-string">'eval'</span>)
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">unless</span> sandbox <span class="hljs-keyword">isnt</span> global <span class="hljs-keyword">or</span> sandbox.module <span class="hljs-keyword">or</span> sandbox.<span class="hljs-built_in">require</span>
Module = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;module&#x27;</span>
sandbox.module = _module = <span class="hljs-keyword">new</span> Module(options.modulename || <span class="hljs-string">&#x27;eval&#x27;</span>)
sandbox.<span class="hljs-built_in">require</span> = _require = <span class="hljs-function"><span class="hljs-params">(path)</span> -&gt;</span> Module._load path, _module, <span class="hljs-literal">true</span>
_module.filename = sandbox.__filename
<span class="hljs-keyword">for</span> r <span class="hljs-keyword">in</span> Object.getOwnPropertyNames <span class="hljs-built_in">require</span> <span class="hljs-keyword">when</span> r <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'paths'</span>, <span class="hljs-string">'arguments'</span>, <span class="hljs-string">'caller'</span>]
<span class="hljs-keyword">for</span> r <span class="hljs-keyword">in</span> <span class="hljs-built_in">Object</span>.getOwnPropertyNames <span class="hljs-built_in">require</span> <span class="hljs-keyword">when</span> r <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">&#x27;paths&#x27;</span>, <span class="hljs-string">&#x27;arguments&#x27;</span>, <span class="hljs-string">&#x27;caller&#x27;</span>]
_require[r] = <span class="hljs-built_in">require</span>[r]</pre></div></div>
</li>
@@ -363,8 +365,8 @@ The CoffeeScript REPL uses this to run the input.</p>
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-14">&#x00a7;</a>
</div>
<p>use the same hack node currently uses for their own REPL</p>
@@ -376,12 +378,12 @@ The CoffeeScript REPL uses this to run the input.</p>
o[k] = v <span class="hljs-keyword">for</span> own k, v <span class="hljs-keyword">of</span> options
o.bare = <span class="hljs-literal">on</span> <span class="hljs-comment"># ensure return value</span>
js = CoffeeScript.compile code, o
<span class="hljs-keyword">if</span> sandbox <span class="hljs-keyword">is</span> <span class="hljs-built_in">global</span>
<span class="hljs-keyword">if</span> sandbox <span class="hljs-keyword">is</span> global
vm.runInThisContext js
<span class="hljs-keyword">else</span>
vm.runInContext js, sandbox
CoffeeScript.register = <span class="hljs-function">-&gt;</span> <span class="hljs-built_in">require</span> <span class="hljs-string">'./register'</span></pre></div></div>
CoffeeScript.register = <span class="hljs-function">-&gt;</span> <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./register&#x27;</span></pre></div></div>
</li>
@@ -389,8 +391,8 @@ CoffeeScript.register = <span class="hljs-function">-&gt;</span> <span class="hl
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-15">&#x00a7;</a>
</div>
<p>Throw error with deprecation warning when depending upon implicit <code>require.extensions</code> registration</p>
@@ -399,12 +401,11 @@ CoffeeScript.register = <span class="hljs-function">-&gt;</span> <span class="hl
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> <span class="hljs-built_in">require</span>.extensions
<span class="hljs-keyword">for</span> ext <span class="hljs-keyword">in</span> CoffeeScript.FILE_EXTENSIONS <span class="hljs-keyword">then</span> <span class="hljs-keyword">do</span> (ext) -&gt;
<span class="hljs-built_in">require</span>.extensions[ext] ?= <span class="hljs-function">-&gt;</span>
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"""
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">&quot;&quot;&quot;
Use CoffeeScript.register() or require the coffeescript/register module to require <span class="hljs-subst">#{ext}</span> files.
"""</span>
&quot;&quot;&quot;</span>
CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params">(filename, options = {})</span> -&gt;</span>
raw = fs.readFileSync filename, <span class="hljs-string">'utf8'</span></pre></div></div>
CoffeeScript._compileRawFileContent = <span class="hljs-function"><span class="hljs-params">(raw, filename, options = {})</span> -&gt;</span></pre></div></div>
</li>
@@ -412,8 +413,8 @@ CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-16">&#x00a7;</a>
</div>
<p>Strip the Unicode byte order mark, if this file begins with one.</p>
@@ -421,11 +422,10 @@ CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params
<div class="content"><div class='highlight'><pre> stripped = <span class="hljs-keyword">if</span> raw.charCodeAt(<span class="hljs-number">0</span>) <span class="hljs-keyword">is</span> <span class="hljs-number">0xFEFF</span> <span class="hljs-keyword">then</span> raw.substring <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> raw
options = Object.assign {}, options,
options = <span class="hljs-built_in">Object</span>.assign {}, options,
filename: filename
literate: helpers.isLiterate filename
sourceFiles: [filename]
inlineMap: <span class="hljs-literal">yes</span> <span class="hljs-comment"># Always generate a source map, so that stack traces line up.</span>
<span class="hljs-keyword">try</span>
answer = CoffeeScript.compile stripped, options
@@ -437,8 +437,8 @@ CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-17">&#x00a7;</a>
</div>
<p>As the filename and code of a dynamically loaded file will be different
from the original file compiled with CoffeeScript.run, add that
@@ -450,7 +450,44 @@ information to error so it can be pretty-printed later.</p>
answer
<span class="hljs-built_in">module</span>.exports = CoffeeScript</pre></div></div>
CoffeeScript._compileFile = <span class="hljs-function"><span class="hljs-params">(filename, options = {})</span> -&gt;</span>
raw = fs.readFileSync filename, <span class="hljs-string">&#x27;utf8&#x27;</span>
CoffeeScript._compileRawFileContent raw, filename, options
module.<span class="hljs-built_in">exports</span> = CoffeeScript</pre></div></div>
</li>
<li id="section-18">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-18">&#x00a7;</a>
</div>
<p>Explicitly define all named exports so that Nodes automatic detection of
named exports from CommonJS packages finds all of them. This enables consuming
packages to write code like <code>import { compile } from &#39;coffeescript&#39;</code>.
Dont simplify this into a loop or similar; the <code>module.exports.name</code> part is
essential for Nodes algorithm to successfully detect the name.</p>
</div>
<div class="content"><div class='highlight'><pre>module.<span class="hljs-built_in">exports</span>.VERSION = CoffeeScript.VERSION
module.<span class="hljs-built_in">exports</span>.FILE_EXTENSIONS = CoffeeScript.FILE_EXTENSIONS
module.<span class="hljs-built_in">exports</span>.helpers = CoffeeScript.helpers
module.<span class="hljs-built_in">exports</span>.registerCompiled = CoffeeScript.registerCompiled
module.<span class="hljs-built_in">exports</span>.compile = CoffeeScript.compile
module.<span class="hljs-built_in">exports</span>.tokens = CoffeeScript.tokens
module.<span class="hljs-built_in">exports</span>.nodes = CoffeeScript.nodes
module.<span class="hljs-built_in">exports</span>.register = CoffeeScript.register
module.<span class="hljs-built_in">exports</span>.<span class="hljs-built_in">eval</span> = CoffeeScript.<span class="hljs-built_in">eval</span>
module.<span class="hljs-built_in">exports</span>.run = CoffeeScript.run
module.<span class="hljs-built_in">exports</span>.transpile = CoffeeScript.transpile
module.<span class="hljs-built_in">exports</span>.patchStackTrace = CoffeeScript.patchStackTrace
module.<span class="hljs-built_in">exports</span>._compileRawFileContent = CoffeeScript._compileRawFileContent
module.<span class="hljs-built_in">exports</span>._compileFile = CoffeeScript._compileFile</pre></div></div>
</li>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -112,13 +112,13 @@
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-1">&#x00a7;</a>
</div>
</div>
<div class="content"><div class='highlight'><pre>{repeat} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span></pre></div></div>
<div class="content"><div class='highlight'><pre>{repeat} = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./helpers&#x27;</span></pre></div></div>
</li>
@@ -126,21 +126,22 @@
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-2">&#x00a7;</a>
</div>
<p>A simple <strong>OptionParser</strong> class to parse option flags from the command-line.
Use it like so:</p>
<pre><code>parser = <span class="hljs-keyword">new</span> OptionParser switches, helpBanner
options = parser.parse process.argv
</code></pre><p>The first non-option is considered to be the start of the file (and file
</code></pre>
<p>The first non-option is considered to be the start of the file (and file
option) list, and all subsequent arguments are left unparsed.</p>
<p>The <code>coffee</code> command uses an instance of <strong>OptionParser</strong> to parse its
command-line arguments in <code>src/command.coffee</code>.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.OptionParser = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OptionParser</span></span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.OptionParser = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OptionParser</span></span></pre></div></div>
</li>
@@ -148,12 +149,13 @@ command-line arguments in <code>src/command.coffee</code>.</p>
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-3">&#x00a7;</a>
</div>
<p>Initialize with a list of valid options, in the form:</p>
<pre><code>[short-flag, long-flag, description]
</code></pre><p>Along with an optional banner for the usage help.</p>
</code></pre>
<p>Along with an optional banner for the usage help.</p>
</div>
@@ -166,8 +168,8 @@ command-line arguments in <code>src/command.coffee</code>.</p>
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-4">&#x00a7;</a>
</div>
<p>Parse the list of arguments, populating an <code>options</code> object with all of the
specified options, and return it. Options after the first non-option
@@ -186,8 +188,8 @@ youre responsible for interpreting the options object.</p>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-5">&#x00a7;</a>
</div>
<p>The CoffeeScript option parser is a little odd; options after the first
non-option argument are treated as non-option arguments themselves.
@@ -208,8 +210,8 @@ line <code>#!/usr/bin/env coffee</code>, or <code>#!/absolute/path/to/coffee</co
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-6">&#x00a7;</a>
</div>
<p>The <code>argument</code> field is added to the rule instance non-destructively by
<code>normalizeArguments</code>.</p>
@@ -226,7 +228,7 @@ line <code>#!/usr/bin/env coffee</code>, or <code>#!/absolute/path/to/coffee</co
<span class="hljs-keyword">else</span>
options[name] = <span class="hljs-literal">true</span>
<span class="hljs-keyword">if</span> positional[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'--'</span>
<span class="hljs-keyword">if</span> positional[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;--&#x27;</span>
options.doubleDashed = <span class="hljs-literal">yes</span>
positional = positional[<span class="hljs-number">1.</span>.]
@@ -239,8 +241,8 @@ line <code>#!/usr/bin/env coffee</code>, or <code>#!/absolute/path/to/coffee</co
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-7">&#x00a7;</a>
</div>
<p>Return the help text for this <strong>OptionParser</strong>, listing and describing all
of the valid options, for <code>--help</code> and such.</p>
@@ -249,13 +251,13 @@ of the valid options, for <code>--help</code> and such.</p>
<div class="content"><div class='highlight'><pre> help: <span class="hljs-function">-&gt;</span>
lines = []
lines.unshift <span class="hljs-string">"<span class="hljs-subst">#{@banner}</span>\n"</span> <span class="hljs-keyword">if</span> @banner
lines.unshift <span class="hljs-string">&quot;<span class="hljs-subst">#{@banner}</span>\n&quot;</span> <span class="hljs-keyword">if</span> @banner
<span class="hljs-keyword">for</span> rule <span class="hljs-keyword">in</span> @rules.ruleList
spaces = <span class="hljs-number">15</span> - rule.longFlag.length
spaces = <span class="hljs-keyword">if</span> spaces &gt; <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> repeat <span class="hljs-string">' '</span>, spaces <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>
letPart = <span class="hljs-keyword">if</span> rule.shortFlag <span class="hljs-keyword">then</span> rule.shortFlag + <span class="hljs-string">', '</span> <span class="hljs-keyword">else</span> <span class="hljs-string">' '</span>
lines.push <span class="hljs-string">' '</span> + letPart + rule.longFlag + spaces + rule.description
<span class="hljs-string">"\n<span class="hljs-subst">#{ lines.join(<span class="hljs-string">'\n'</span>) }</span>\n"</span></pre></div></div>
spaces = <span class="hljs-keyword">if</span> spaces &gt; <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> repeat <span class="hljs-string">&#x27; &#x27;</span>, spaces <span class="hljs-keyword">else</span> <span class="hljs-string">&#x27;&#x27;</span>
letPart = <span class="hljs-keyword">if</span> rule.shortFlag <span class="hljs-keyword">then</span> rule.shortFlag + <span class="hljs-string">&#x27;, &#x27;</span> <span class="hljs-keyword">else</span> <span class="hljs-string">&#x27; &#x27;</span>
lines.push <span class="hljs-string">&#x27; &#x27;</span> + letPart + rule.longFlag + spaces + rule.description
<span class="hljs-string">&quot;\n<span class="hljs-subst">#{ lines.join(<span class="hljs-string">&#x27;\n&#x27;</span>) }</span>\n&quot;</span></pre></div></div>
</li>
@@ -263,8 +265,8 @@ of the valid options, for <code>--help</code> and such.</p>
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-8">&#x00a7;</a>
</div>
<h2 id="helpers">Helpers</h2>
@@ -276,8 +278,8 @@ of the valid options, for <code>--help</code> and such.</p>
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-9">&#x00a7;</a>
</div>
</div>
@@ -288,8 +290,8 @@ of the valid options, for <code>--help</code> and such.</p>
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-10">&#x00a7;</a>
</div>
<p>Regex matchers for option flags on the command line and their rules.</p>
@@ -305,8 +307,8 @@ MULTI_FLAG = <span class="hljs-regexp">/^-(\w{2,})/</span></pre></div></div>
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-11">&#x00a7;</a>
</div>
<p>Matches the long flag part of a rule for an option with an argument. Not
applied to anything in process.argv.</p>
@@ -321,8 +323,8 @@ applied to anything in process.argv.</p>
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-12">&#x00a7;</a>
</div>
<p>Build and return the list of option rules. If the optional <em>short-flag</em> is
unspecified, leave it out by padding with <code>null</code>.</p>
@@ -342,8 +344,8 @@ unspecified, leave it out by padding with <code>null</code>.</p>
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-13">&#x00a7;</a>
</div>
<p><code>shortFlag</code> is null if not provided in the rule.</p>
@@ -351,8 +353,8 @@ unspecified, leave it out by padding with <code>null</code>.</p>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">for</span> flag <span class="hljs-keyword">in</span> [rule.shortFlag, rule.longFlag] <span class="hljs-keyword">when</span> flag?
<span class="hljs-keyword">if</span> flagDict[flag]?
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"flag <span class="hljs-subst">#{flag}</span> for switch <span class="hljs-subst">#{rule.name}</span>
was already declared for switch <span class="hljs-subst">#{flagDict[flag].name}</span>"</span>
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">&quot;flag <span class="hljs-subst">#{flag}</span> for switch <span class="hljs-subst">#{rule.name}</span>
was already declared for switch <span class="hljs-subst">#{flagDict[flag].name}</span>&quot;</span>
flagDict[flag] = rule
{ruleList, flagDict}</pre></div></div>
@@ -363,8 +365,8 @@ unspecified, leave it out by padding with <code>null</code>.</p>
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-14">&#x00a7;</a>
</div>
<p>Build a rule from a <code>-o</code> short flag, a <code>--output [DIR]</code> long flag, and the
description of what the option does.</p>
@@ -376,7 +378,7 @@ description of what the option does.</p>
shortFlag = shortFlag?.match(SHORT_FLAG)[<span class="hljs-number">1</span>]
longFlag = longFlag.match(LONG_FLAG)[<span class="hljs-number">1</span>]
{
name: longFlag.replace <span class="hljs-regexp">/^--/</span>, <span class="hljs-string">''</span>
name: longFlag.replace <span class="hljs-regexp">/^--/</span>, <span class="hljs-string">&#x27;&#x27;</span>
shortFlag: shortFlag
longFlag: longFlag
description: description
@@ -396,8 +398,8 @@ description of what the option does.</p>
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-15">&#x00a7;</a>
</div>
<p>If the previous argument given to the script was an option that uses the
next command-line argument as its argument, create copy of the options
@@ -406,19 +408,19 @@ rule with an <code>argument</code> field.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> needsArgOpt?
withArg = Object.assign {}, needsArgOpt.rule, {argument: arg}
withArg = <span class="hljs-built_in">Object</span>.assign {}, needsArgOpt.rule, {argument: arg}
rules.push withArg
needsArgOpt = <span class="hljs-literal">null</span>
<span class="hljs-keyword">continue</span>
multiFlags = arg.match(MULTI_FLAG)?[<span class="hljs-number">1</span>]
.split(<span class="hljs-string">''</span>)
.map (flagName) -&gt; <span class="hljs-string">"-<span class="hljs-subst">#{flagName}</span>"</span>
.split(<span class="hljs-string">&#x27;&#x27;</span>)
.map (flagName) -&gt; <span class="hljs-string">&quot;-<span class="hljs-subst">#{flagName}</span>&quot;</span>
<span class="hljs-keyword">if</span> multiFlags?
multiOpts = multiFlags.map (flag) -&gt;
rule = flagDict[flag]
<span class="hljs-keyword">unless</span> rule?
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"unrecognized option <span class="hljs-subst">#{flag}</span> in multi-flag <span class="hljs-subst">#{arg}</span>"</span>
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">&quot;unrecognized option <span class="hljs-subst">#{flag}</span> in multi-flag <span class="hljs-subst">#{arg}</span>&quot;</span>
{rule, flag}</pre></div></div>
</li>
@@ -427,8 +429,8 @@ rule with an <code>argument</code> field.</p>
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-16">&#x00a7;</a>
</div>
<p>Only the last flag in a multi-flag may have an argument.</p>
@@ -437,8 +439,8 @@ rule with an <code>argument</code> field.</p>
<div class="content"><div class='highlight'><pre> [innerOpts..., lastOpt] = multiOpts
<span class="hljs-keyword">for</span> {rule, flag} <span class="hljs-keyword">in</span> innerOpts
<span class="hljs-keyword">if</span> rule.hasArgument
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"cannot use option <span class="hljs-subst">#{flag}</span> in multi-flag <span class="hljs-subst">#{arg}</span> except
as the last option, because it needs an argument"</span>
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">&quot;cannot use option <span class="hljs-subst">#{flag}</span> in multi-flag <span class="hljs-subst">#{arg}</span> except
as the last option, because it needs an argument&quot;</span>
rules.push rule
<span class="hljs-keyword">if</span> lastOpt.rule.hasArgument
needsArgOpt = lastOpt
@@ -447,7 +449,7 @@ rule with an <code>argument</code> field.</p>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ([LONG_FLAG, SHORT_FLAG].some (pat) -&gt; arg.match(pat)?)
singleRule = flagDict[arg]
<span class="hljs-keyword">unless</span> singleRule?
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"unrecognized option <span class="hljs-subst">#{arg}</span>"</span>
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">&quot;unrecognized option <span class="hljs-subst">#{arg}</span>&quot;</span>
<span class="hljs-keyword">if</span> singleRule.hasArgument
needsArgOpt = {rule: singleRule, flag: arg}
<span class="hljs-keyword">else</span>
@@ -460,8 +462,8 @@ rule with an <code>argument</code> field.</p>
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-17">&#x00a7;</a>
</div>
<p>This is a positional argument.</p>
@@ -471,8 +473,8 @@ rule with an <code>argument</code> field.</p>
<span class="hljs-keyword">break</span>
<span class="hljs-keyword">if</span> needsArgOpt?
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"value required for <span class="hljs-subst">#{needsArgOpt.flag}</span>, but it was the last
argument provided"</span>
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">&quot;value required for <span class="hljs-subst">#{needsArgOpt.flag}</span>, but it was the last
argument provided&quot;</span>
{rules, positional}</pre></div></div>
</li>

0
docs/v2/annotated-source/public/fonts/roboto-black.eot Executable file → Normal file
View File

0
docs/v2/annotated-source/public/fonts/roboto-black.ttf Executable file → Normal file
View File

View File

View File

@@ -112,16 +112,18 @@
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-1">&#x00a7;</a>
</div>
</div>
<div class="content"><div class='highlight'><pre>CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./'</span>
child_process = <span class="hljs-built_in">require</span> <span class="hljs-string">'child_process'</span>
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span></pre></div></div>
<div class="content"><div class='highlight'><pre>CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./&#x27;</span>
child_process = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;child_process&#x27;</span>
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./helpers&#x27;</span>
path = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;path&#x27;</span>
{patchStackTrace} = CoffeeScript</pre></div></div>
</li>
@@ -129,17 +131,21 @@ path = <span class="hljs-built_in">require</span> <span class="hljs-str
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-2">&#x00a7;</a>
</div>
<p>Load and run a CoffeeScript file for Node, stripping any <code>BOM</code>s.</p>
<p>Check if Nodes built-in source map stack trace transformations are enabled.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">loadFile</span> = <span class="hljs-params">(<span class="hljs-built_in">module</span>, filename)</span> -&gt;</span>
options = <span class="hljs-built_in">module</span>.options <span class="hljs-keyword">or</span> getRootModule(<span class="hljs-built_in">module</span>).options
answer = CoffeeScript._compileFile filename, options
<span class="hljs-built_in">module</span>._compile answer, filename</pre></div></div>
<div class="content"><div class='highlight'><pre>nodeSourceMapsSupportEnabled = process? <span class="hljs-keyword">and</span> (
process.execArgv.includes(<span class="hljs-string">&#x27;--enable-source-maps&#x27;</span>) <span class="hljs-keyword">or</span>
process.env.NODE_OPTIONS?.includes(<span class="hljs-string">&#x27;--enable-source-maps&#x27;</span>)
)
<span class="hljs-keyword">unless</span> <span class="hljs-built_in">Error</span>.prepareStackTrace <span class="hljs-keyword">or</span> nodeSourceMapsSupportEnabled
cacheSourceMaps = <span class="hljs-literal">true</span>
patchStackTrace()</pre></div></div>
</li>
@@ -147,8 +153,44 @@ path = <span class="hljs-built_in">require</span> <span class="hljs-str
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-3">&#x00a7;</a>
</div>
<p>Load and run a CoffeeScript file for Node, stripping any <code>BOM</code>s.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">loadFile</span> = <span class="hljs-params">(module, filename)</span> -&gt;</span>
options = module.options <span class="hljs-keyword">or</span> getRootModule(module).options <span class="hljs-keyword">or</span> {}</pre></div></div>
</li>
<li id="section-4">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-4">&#x00a7;</a>
</div>
<p>Currently <code>CoffeeScript.compile</code> caches all source maps if present. They
are available in <code>getSourceMap</code> retrieved by <code>filename</code>.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> cacheSourceMaps <span class="hljs-keyword">or</span> nodeSourceMapsSupportEnabled
options.inlineMap = <span class="hljs-literal">true</span>
js = CoffeeScript._compileFile filename, options
module._compile js, filename</pre></div></div>
</li>
<li id="section-5">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-5">&#x00a7;</a>
</div>
<p>If the installed version of Node supports <code>require.extensions</code>, register
CoffeeScript as an extension.</p>
@@ -162,61 +204,21 @@ CoffeeScript as an extension.</p>
</li>
<li id="section-4">
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-6">&#x00a7;</a>
</div>
<p>Patch Nodes module loader to be able to handle multi-dot extensions.
This is a horrible thing that should not be required.</p>
</div>
<div class="content"><div class='highlight'><pre> Module = <span class="hljs-built_in">require</span> <span class="hljs-string">'module'</span>
<div class="content"><div class='highlight'><pre> Module = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;module&#x27;</span>
<span class="hljs-function">
<span class="hljs-title">findExtension</span> = <span class="hljs-params">(filename)</span> -&gt;</span>
extensions = path.basename(filename).split <span class="hljs-string">'.'</span></pre></div></div>
</li>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p>Remove the initial dot from dotfiles.</p>
</div>
<div class="content"><div class='highlight'><pre> extensions.shift() <span class="hljs-keyword">if</span> extensions[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span></pre></div></div>
</li>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p>Start with the longest possible extension and work our way shortwards.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">while</span> extensions.shift()
curExtension = <span class="hljs-string">'.'</span> + extensions.join <span class="hljs-string">'.'</span>
<span class="hljs-keyword">return</span> curExtension <span class="hljs-keyword">if</span> Module._extensions[curExtension]
<span class="hljs-string">'.js'</span>
Module::load = <span class="hljs-function"><span class="hljs-params">(filename)</span> -&gt;</span>
@filename = filename
@paths = Module._nodeModulePaths path.dirname filename
extension = findExtension filename
Module._extensions[extension](<span class="hljs-keyword">this</span>, filename)
@loaded = <span class="hljs-literal">true</span></pre></div></div>
extensions = path.basename(filename).split <span class="hljs-string">&#x27;.&#x27;</span></pre></div></div>
</li>
@@ -224,8 +226,48 @@ This is a horrible thing that should not be required.</p>
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-7">&#x00a7;</a>
</div>
<p>Remove the initial dot from dotfiles.</p>
</div>
<div class="content"><div class='highlight'><pre> extensions.shift() <span class="hljs-keyword">if</span> extensions[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;&#x27;</span></pre></div></div>
</li>
<li id="section-8">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-8">&#x00a7;</a>
</div>
<p>Start with the longest possible extension and work our way shortwards.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">while</span> extensions.shift()
curExtension = <span class="hljs-string">&#x27;.&#x27;</span> + extensions.join <span class="hljs-string">&#x27;.&#x27;</span>
<span class="hljs-keyword">return</span> curExtension <span class="hljs-keyword">if</span> Module._extensions[curExtension]
<span class="hljs-string">&#x27;.js&#x27;</span>
Module::load = <span class="hljs-function"><span class="hljs-params">(filename)</span> -&gt;</span>
@filename = filename
@paths = Module._nodeModulePaths path.dirname filename
extension = findExtension filename
Module._extensions[extension](this, filename)
@loaded = <span class="hljs-literal">true</span></pre></div></div>
</li>
<li id="section-9">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-9">&#x00a7;</a>
</div>
<p>If were on Node, patch <code>child_process.fork</code> so that Coffee scripts are able
to fork both CoffeeScript files, and JavaScript files, directly.</p>
@@ -234,10 +276,10 @@ to fork both CoffeeScript files, and JavaScript files, directly.</p>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> child_process
{fork} = child_process
binary = <span class="hljs-built_in">require</span>.resolve <span class="hljs-string">'../../bin/coffee'</span>
binary = <span class="hljs-built_in">require</span>.resolve <span class="hljs-string">&#x27;../../bin/coffee&#x27;</span>
child_process.fork = <span class="hljs-function"><span class="hljs-params">(path, args, options)</span> -&gt;</span>
<span class="hljs-keyword">if</span> helpers.isCoffee path
<span class="hljs-keyword">unless</span> Array.isArray args
<span class="hljs-keyword">unless</span> <span class="hljs-built_in">Array</span>.isArray args
options = args <span class="hljs-keyword">or</span> {}
args = []
args = [path].concat args
@@ -247,18 +289,18 @@ to fork both CoffeeScript files, and JavaScript files, directly.</p>
</li>
<li id="section-8">
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-10">&#x00a7;</a>
</div>
<p>Utility function to find the <code>options</code> object attached to the topmost module.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">getRootModule</span> = <span class="hljs-params">(<span class="hljs-built_in">module</span>)</span> -&gt;</span>
<span class="hljs-keyword">if</span> <span class="hljs-built_in">module</span>.parent <span class="hljs-keyword">then</span> getRootModule <span class="hljs-built_in">module</span>.parent <span class="hljs-keyword">else</span> <span class="hljs-built_in">module</span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">getRootModule</span> = <span class="hljs-params">(module)</span> -&gt;</span>
<span class="hljs-keyword">if</span> module.parent <span class="hljs-keyword">then</span> getRootModule module.parent <span class="hljs-keyword">else</span> module</pre></div></div>
</li>

View File

@@ -112,27 +112,27 @@
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-1">&#x00a7;</a>
</div>
</div>
<div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
vm = <span class="hljs-built_in">require</span> <span class="hljs-string">'vm'</span>
nodeREPL = <span class="hljs-built_in">require</span> <span class="hljs-string">'repl'</span>
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./'</span>
{merge, updateSyntaxError} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
<div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;fs&#x27;</span>
path = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;path&#x27;</span>
vm = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;vm&#x27;</span>
nodeREPL = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;repl&#x27;</span>
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./&#x27;</span>
{merge, updateSyntaxError} = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./helpers&#x27;</span>
sawSIGINT = <span class="hljs-literal">no</span>
transpile = <span class="hljs-literal">no</span>
replDefaults =
prompt: <span class="hljs-string">'coffee&gt; '</span>,
prompt: <span class="hljs-string">&#x27;coffee&gt; &#x27;</span>,
historyFile: <span class="hljs-keyword">do</span> -&gt;
historyPath = process.env.XDG_CACHE_HOME <span class="hljs-keyword">or</span> process.env.HOME
path.join historyPath, <span class="hljs-string">'.coffee_history'</span> <span class="hljs-keyword">if</span> historyPath
path.join historyPath, <span class="hljs-string">&#x27;.coffee_history&#x27;</span> <span class="hljs-keyword">if</span> historyPath
historyMaxInputSize: <span class="hljs-number">10240</span>
eval: <span class="hljs-function"><span class="hljs-params">(input, context, filename, cb)</span> -&gt;</span></pre></div></div>
@@ -142,14 +142,14 @@ replDefaults =
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-2">&#x00a7;</a>
</div>
<p>XXX: multiline hack.</p>
</div>
<div class="content"><div class='highlight'><pre> input = input.replace <span class="hljs-regexp">/\uFF00/g</span>, <span class="hljs-string">'\n'</span></pre></div></div>
<div class="content"><div class='highlight'><pre> input = input.replace <span class="hljs-regexp">/\uFF00/g</span>, <span class="hljs-string">&#x27;\n&#x27;</span></pre></div></div>
</li>
@@ -157,15 +157,15 @@ replDefaults =
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-3">&#x00a7;</a>
</div>
<p>Nodes REPL sends the input ending with a newline and then wrapped in
parens. Unwrap all that.</p>
</div>
<div class="content"><div class='highlight'><pre> input = input.replace <span class="hljs-regexp">/^\(([\s\S]*)\n\)$/m</span>, <span class="hljs-string">'$1'</span></pre></div></div>
<div class="content"><div class='highlight'><pre> input = input.replace <span class="hljs-regexp">/^\(([\s\S]*)\n\)$/m</span>, <span class="hljs-string">&#x27;$1&#x27;</span></pre></div></div>
</li>
@@ -173,15 +173,15 @@ parens. Unwrap all that.</p>
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-4">&#x00a7;</a>
</div>
<p>Nodes REPL v6.9.1+ sends the input wrapped in a try/catch statement.
Unwrap that too.</p>
</div>
<div class="content"><div class='highlight'><pre> input = input.replace <span class="hljs-regexp">/^\s*try\s*{([\s\S]*)}\s*catch.*$/m</span>, <span class="hljs-string">'$1'</span></pre></div></div>
<div class="content"><div class='highlight'><pre> input = input.replace <span class="hljs-regexp">/^\s*try\s*{([\s\S]*)}\s*catch.*$/m</span>, <span class="hljs-string">&#x27;$1&#x27;</span></pre></div></div>
</li>
@@ -189,14 +189,14 @@ Unwrap that too.</p>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-5">&#x00a7;</a>
</div>
<p>Require AST nodes to do some AST manipulation.</p>
</div>
<div class="content"><div class='highlight'><pre> {Block, Assign, Value, Literal, Call, Code} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./nodes'</span>
<div class="content"><div class='highlight'><pre> {Block, Assign, Value, Literal, Call, Code, Root} = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;./nodes&#x27;</span>
<span class="hljs-keyword">try</span></pre></div></div>
@@ -206,8 +206,8 @@ Unwrap that too.</p>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-6">&#x00a7;</a>
</div>
<p>Tokenize the clean input.</p>
@@ -221,19 +221,19 @@ Unwrap that too.</p>
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-7">&#x00a7;</a>
</div>
<p>Filter out tokens generated just to hold comments.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> tokens.length &gt;= <span class="hljs-number">2</span> <span class="hljs-keyword">and</span> tokens[<span class="hljs-number">0</span>].generated <span class="hljs-keyword">and</span>
tokens[<span class="hljs-number">0</span>].comments?.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> tokens[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span> <span class="hljs-keyword">and</span>
tokens[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'TERMINATOR'</span>
tokens[<span class="hljs-number">0</span>].comments?.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> <span class="hljs-string">&quot;<span class="hljs-subst">#{tokens[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>]}</span>&quot;</span> <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;&#x27;</span> <span class="hljs-keyword">and</span>
tokens[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;TERMINATOR&#x27;</span>
tokens = tokens[<span class="hljs-number">2.</span>..]
<span class="hljs-keyword">if</span> tokens.length &gt;= <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> tokens[tokens.length - <span class="hljs-number">1</span>].generated <span class="hljs-keyword">and</span>
tokens[tokens.length - <span class="hljs-number">1</span>].comments?.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> tokens[tokens.length - <span class="hljs-number">1</span>][<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span>
tokens[tokens.length - <span class="hljs-number">1</span>].comments?.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> <span class="hljs-string">&quot;<span class="hljs-subst">#{tokens[tokens.length - <span class="hljs-number">1</span>][<span class="hljs-number">1</span>]}</span>&quot;</span> <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;&#x27;</span>
tokens.pop()</pre></div></div>
</li>
@@ -242,14 +242,14 @@ Unwrap that too.</p>
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-8">&#x00a7;</a>
</div>
<p>Collect referenced variable names just like in <code>CoffeeScript.compile</code>.</p>
</div>
<div class="content"><div class='highlight'><pre> referencedVars = (token[<span class="hljs-number">1</span>] <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'IDENTIFIER'</span>)</pre></div></div>
<div class="content"><div class='highlight'><pre> referencedVars = (token[<span class="hljs-number">1</span>] <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;IDENTIFIER&#x27;</span>)</pre></div></div>
</li>
@@ -257,14 +257,14 @@ Unwrap that too.</p>
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-9">&#x00a7;</a>
</div>
<p>Generate the AST of the tokens.</p>
</div>
<div class="content"><div class='highlight'><pre> ast = CoffeeScript.nodes tokens</pre></div></div>
<div class="content"><div class='highlight'><pre> ast = CoffeeScript.nodes(tokens).body</pre></div></div>
</li>
@@ -272,14 +272,14 @@ Unwrap that too.</p>
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-10">&#x00a7;</a>
</div>
<p>Add assignment to <code>__</code> variable to force the input to be an expression.</p>
</div>
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Assign (<span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal <span class="hljs-string">'__'</span>), ast, <span class="hljs-string">'='</span>]</pre></div></div>
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Assign (<span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal <span class="hljs-string">&#x27;__&#x27;</span>), ast, <span class="hljs-string">&#x27;=&#x27;</span>]</pre></div></div>
</li>
@@ -287,8 +287,8 @@ Unwrap that too.</p>
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-11">&#x00a7;</a>
</div>
<p>Wrap the expression in a closure to support top-level <code>await</code>.</p>
@@ -303,15 +303,15 @@ Unwrap that too.</p>
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-12">&#x00a7;</a>
</div>
<p>Invoke the wrapping closure.</p>
</div>
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Call ast]
js = ast.compile {bare: <span class="hljs-literal">yes</span>, locals: Object.keys(context), referencedVars, sharedScope: <span class="hljs-literal">yes</span>}
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Root <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Call ast]
js = ast.compile {bare: <span class="hljs-literal">yes</span>, locals: <span class="hljs-built_in">Object</span>.keys(context), referencedVars, sharedScope: <span class="hljs-literal">yes</span>}
<span class="hljs-keyword">if</span> transpile
js = transpile.transpile(js, transpile.options).code</pre></div></div>
@@ -321,15 +321,15 @@ Unwrap that too.</p>
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-13">&#x00a7;</a>
</div>
<p>Strip <code>&quot;use strict&quot;</code>, to avoid an exception on assigning to
undeclared variable <code>__</code>.</p>
</div>
<div class="content"><div class='highlight'><pre> js = js.replace <span class="hljs-regexp">/^"use strict"|^'use strict'/</span>, <span class="hljs-string">''</span>
<div class="content"><div class='highlight'><pre> js = js.replace <span class="hljs-regexp">/^&quot;use strict&quot;|^&#x27;use strict&#x27;/</span>, <span class="hljs-string">&#x27;&#x27;</span>
result = runInContext js, context, filename</pre></div></div>
</li>
@@ -338,8 +338,8 @@ undeclared variable <code>__</code>.</p>
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-14">&#x00a7;</a>
</div>
<p>Await an async result, if necessary.</p>
@@ -359,8 +359,8 @@ undeclared variable <code>__</code>.</p>
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-15">&#x00a7;</a>
</div>
<p>ASTs <code>compile</code> does not add source code information to syntax errors.</p>
@@ -370,13 +370,13 @@ undeclared variable <code>__</code>.</p>
cb err
<span class="hljs-function">
<span class="hljs-title">runInContext</span> = <span class="hljs-params">(js, context, filename)</span> -&gt;</span>
<span class="hljs-keyword">if</span> context <span class="hljs-keyword">is</span> <span class="hljs-built_in">global</span>
<span class="hljs-keyword">if</span> context <span class="hljs-keyword">is</span> global
vm.runInThisContext js, filename
<span class="hljs-keyword">else</span>
vm.runInContext js, context, filename
<span class="hljs-function">
<span class="hljs-title">addMultilineHandler</span> = <span class="hljs-params">(repl)</span> -&gt;</span>
{rli, inputStream, outputStream} = repl</pre></div></div>
{inputStream, outputStream} = repl</pre></div></div>
</li>
@@ -384,8 +384,8 @@ undeclared variable <code>__</code>.</p>
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-16">&#x00a7;</a>
</div>
<p>Node 0.11.12 changed API, prompt is now _prompt.</p>
@@ -395,9 +395,9 @@ undeclared variable <code>__</code>.</p>
multiline =
enabled: <span class="hljs-literal">off</span>
initialPrompt: origPrompt.replace <span class="hljs-regexp">/^[^&gt; ]*/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -&gt;</span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">'-'</span>
prompt: origPrompt.replace <span class="hljs-regexp">/^[^&gt; ]*&gt;?/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -&gt;</span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">'.'</span>
buffer: <span class="hljs-string">''</span></pre></div></div>
initialPrompt: origPrompt.replace <span class="hljs-regexp">/^[^&gt; ]*/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -&gt;</span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">&#x27;-&#x27;</span>
prompt: origPrompt.replace <span class="hljs-regexp">/^[^&gt; ]*&gt;?/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -&gt;</span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">&#x27;.&#x27;</span>
buffer: <span class="hljs-string">&#x27;&#x27;</span></pre></div></div>
</li>
@@ -405,22 +405,22 @@ undeclared variable <code>__</code>.</p>
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-17">&#x00a7;</a>
</div>
<p>Proxy nodes line listener</p>
</div>
<div class="content"><div class='highlight'><pre> nodeLineListener = rli.listeners(<span class="hljs-string">'line'</span>)[<span class="hljs-number">0</span>]
rli.removeListener <span class="hljs-string">'line'</span>, nodeLineListener
rli.<span class="hljs-literal">on</span> <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(cmd)</span> -&gt;</span>
<div class="content"><div class='highlight'><pre> nodeLineListener = repl.listeners(<span class="hljs-string">&#x27;line&#x27;</span>)[<span class="hljs-number">0</span>]
repl.removeListener <span class="hljs-string">&#x27;line&#x27;</span>, nodeLineListener
repl.<span class="hljs-literal">on</span> <span class="hljs-string">&#x27;line&#x27;</span>, <span class="hljs-function"><span class="hljs-params">(cmd)</span> -&gt;</span>
<span class="hljs-keyword">if</span> multiline.enabled
multiline.buffer += <span class="hljs-string">"<span class="hljs-subst">#{cmd}</span>\n"</span>
rli.setPrompt multiline.prompt
rli.prompt <span class="hljs-literal">true</span>
multiline.buffer += <span class="hljs-string">&quot;<span class="hljs-subst">#{cmd}</span>\n&quot;</span>
repl.setPrompt multiline.prompt
repl.prompt <span class="hljs-literal">true</span>
<span class="hljs-keyword">else</span>
rli.setPrompt origPrompt
repl.setPrompt origPrompt
nodeLineListener cmd
<span class="hljs-keyword">return</span></pre></div></div>
@@ -430,15 +430,15 @@ undeclared variable <code>__</code>.</p>
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-18">&#x00a7;</a>
</div>
<p>Handle Ctrl-v</p>
</div>
<div class="content"><div class='highlight'><pre> inputStream.<span class="hljs-literal">on</span> <span class="hljs-string">'keypress'</span>, <span class="hljs-function"><span class="hljs-params">(char, key)</span> -&gt;</span>
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> key <span class="hljs-keyword">and</span> key.ctrl <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> key.meta <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> key.shift <span class="hljs-keyword">and</span> key.name <span class="hljs-keyword">is</span> <span class="hljs-string">'v'</span>
<div class="content"><div class='highlight'><pre> inputStream.<span class="hljs-literal">on</span> <span class="hljs-string">&#x27;keypress&#x27;</span>, <span class="hljs-function"><span class="hljs-params">(char, key)</span> -&gt;</span>
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> key <span class="hljs-keyword">and</span> key.ctrl <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> key.meta <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> key.shift <span class="hljs-keyword">and</span> key.name <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;v&#x27;</span>
<span class="hljs-keyword">if</span> multiline.enabled</pre></div></div>
</li>
@@ -447,8 +447,8 @@ undeclared variable <code>__</code>.</p>
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-19">&#x00a7;</a>
</div>
<p>allow arbitrarily switching between modes any time before multiple lines are entered</p>
@@ -456,8 +456,8 @@ undeclared variable <code>__</code>.</p>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">unless</span> multiline.buffer.match <span class="hljs-regexp">/\n/</span>
multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
rli.setPrompt origPrompt
rli.prompt <span class="hljs-literal">true</span>
repl.setPrompt origPrompt
repl.prompt <span class="hljs-literal">true</span>
<span class="hljs-keyword">return</span></pre></div></div>
</li>
@@ -466,14 +466,14 @@ undeclared variable <code>__</code>.</p>
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-20">&#x00a7;</a>
</div>
<p>no-op unless the current line is empty</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> rli.line? <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> rli.line.match <span class="hljs-regexp">/^\s*$/</span></pre></div></div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> repl.line? <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> repl.line.match <span class="hljs-regexp">/^\s*$/</span></pre></div></div>
</li>
@@ -481,18 +481,18 @@ undeclared variable <code>__</code>.</p>
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-21">&#x00a7;</a>
</div>
<p>eval, print, loop</p>
</div>
<div class="content"><div class='highlight'><pre> multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
rli.line = <span class="hljs-string">''</span>
rli.cursor = <span class="hljs-number">0</span>
rli.output.cursorTo <span class="hljs-number">0</span>
rli.output.clearLine <span class="hljs-number">1</span></pre></div></div>
repl.line = <span class="hljs-string">&#x27;&#x27;</span>
repl.cursor = <span class="hljs-number">0</span>
repl.output.cursorTo <span class="hljs-number">0</span>
repl.output.clearLine <span class="hljs-number">1</span></pre></div></div>
</li>
@@ -500,20 +500,20 @@ undeclared variable <code>__</code>.</p>
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-22">&#x00a7;</a>
</div>
<p>XXX: multiline hack</p>
</div>
<div class="content"><div class='highlight'><pre> multiline.buffer = multiline.buffer.replace <span class="hljs-regexp">/\n/g</span>, <span class="hljs-string">'\uFF00'</span>
rli.emit <span class="hljs-string">'line'</span>, multiline.buffer
multiline.buffer = <span class="hljs-string">''</span>
<div class="content"><div class='highlight'><pre> multiline.buffer = multiline.buffer.replace <span class="hljs-regexp">/\n/g</span>, <span class="hljs-string">&#x27;\uFF00&#x27;</span>
repl.emit <span class="hljs-string">&#x27;line&#x27;</span>, multiline.buffer
multiline.buffer = <span class="hljs-string">&#x27;&#x27;</span>
<span class="hljs-keyword">else</span>
multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
rli.setPrompt multiline.initialPrompt
rli.prompt <span class="hljs-literal">true</span>
repl.setPrompt multiline.initialPrompt
repl.prompt <span class="hljs-literal">true</span>
<span class="hljs-keyword">return</span></pre></div></div>
</li>
@@ -522,8 +522,8 @@ undeclared variable <code>__</code>.</p>
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-23">&#x00a7;</a>
</div>
<p>Store and load command history from a file</p>
@@ -539,15 +539,15 @@ undeclared variable <code>__</code>.</p>
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-24">&#x00a7;</a>
</div>
<p>Get file info and at most maxSize of command history</p>
</div>
<div class="content"><div class='highlight'><pre> stat = fs.statSync filename
size = Math.min maxSize, stat.size</pre></div></div>
size = <span class="hljs-built_in">Math</span>.min maxSize, stat.size</pre></div></div>
</li>
@@ -555,14 +555,14 @@ undeclared variable <code>__</code>.</p>
<li id="section-25">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-25">&#x00a7;</a>
</div>
<p>Read last <code>size</code> bytes from the file</p>
</div>
<div class="content"><div class='highlight'><pre> readFd = fs.openSync filename, <span class="hljs-string">'r'</span>
<div class="content"><div class='highlight'><pre> readFd = fs.openSync filename, <span class="hljs-string">&#x27;r&#x27;</span>
buffer = Buffer.alloc size
fs.readSync readFd, buffer, <span class="hljs-number">0</span>, size, stat.size - size
fs.closeSync readFd</pre></div></div>
@@ -573,14 +573,14 @@ undeclared variable <code>__</code>.</p>
<li id="section-26">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-26">&#x00a7;</a>
</div>
<p>Set the history on the interpreter</p>
</div>
<div class="content"><div class='highlight'><pre> repl.rli.history = buffer.toString().split(<span class="hljs-string">'\n'</span>).reverse()</pre></div></div>
<div class="content"><div class='highlight'><pre> repl.history = buffer.toString().split(<span class="hljs-string">&#x27;\n&#x27;</span>).reverse()</pre></div></div>
</li>
@@ -588,14 +588,14 @@ undeclared variable <code>__</code>.</p>
<li id="section-27">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-27">&#x00a7;</a>
</div>
<p>If the history file was truncated we should pop off a potential partial line</p>
</div>
<div class="content"><div class='highlight'><pre> repl.rli.history.pop() <span class="hljs-keyword">if</span> stat.size &gt; maxSize</pre></div></div>
<div class="content"><div class='highlight'><pre> repl.history.pop() <span class="hljs-keyword">if</span> stat.size &gt; maxSize</pre></div></div>
</li>
@@ -603,21 +603,21 @@ undeclared variable <code>__</code>.</p>
<li id="section-28">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-28">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-28">&#x00a7;</a>
</div>
<p>Shift off the final blank newline</p>
</div>
<div class="content"><div class='highlight'><pre> repl.rli.history.shift() <span class="hljs-keyword">if</span> repl.rli.history[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span>
repl.rli.historyIndex = <span class="hljs-number">-1</span>
lastLine = repl.rli.history[<span class="hljs-number">0</span>]
<div class="content"><div class='highlight'><pre> repl.history.shift() <span class="hljs-keyword">if</span> repl.history[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;&#x27;</span>
repl.historyIndex = <span class="hljs-number">-1</span>
lastLine = repl.history[<span class="hljs-number">0</span>]
fd = fs.openSync filename, <span class="hljs-string">'a'</span>
fd = fs.openSync filename, <span class="hljs-string">&#x27;a&#x27;</span>
repl.rli.addListener <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -&gt;</span>
<span class="hljs-keyword">if</span> code <span class="hljs-keyword">and</span> code.length <span class="hljs-keyword">and</span> code <span class="hljs-keyword">isnt</span> <span class="hljs-string">'.history'</span> <span class="hljs-keyword">and</span> code <span class="hljs-keyword">isnt</span> <span class="hljs-string">'.exit'</span> <span class="hljs-keyword">and</span> lastLine <span class="hljs-keyword">isnt</span> code</pre></div></div>
repl.addListener <span class="hljs-string">&#x27;line&#x27;</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -&gt;</span>
<span class="hljs-keyword">if</span> code <span class="hljs-keyword">and</span> code.length <span class="hljs-keyword">and</span> code <span class="hljs-keyword">isnt</span> <span class="hljs-string">&#x27;.history&#x27;</span> <span class="hljs-keyword">and</span> code <span class="hljs-keyword">isnt</span> <span class="hljs-string">&#x27;.exit&#x27;</span> <span class="hljs-keyword">and</span> lastLine <span class="hljs-keyword">isnt</span> code</pre></div></div>
</li>
@@ -625,14 +625,14 @@ undeclared variable <code>__</code>.</p>
<li id="section-29">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-29">&#x00a7;</a>
</div>
<p>Save the latest command in the file</p>
</div>
<div class="content"><div class='highlight'><pre> fs.writeSync fd, <span class="hljs-string">"<span class="hljs-subst">#{code}</span>\n"</span>
<div class="content"><div class='highlight'><pre> fs.writeSync fd, <span class="hljs-string">&quot;<span class="hljs-subst">#{code}</span>\n&quot;</span>
lastLine = code</pre></div></div>
</li>
@@ -641,15 +641,15 @@ undeclared variable <code>__</code>.</p>
<li id="section-30">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-30">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-30">&#x00a7;</a>
</div>
<p>XXX: The SIGINT event from REPLServer is undocumented, so this is a bit fragile</p>
</div>
<div class="content"><div class='highlight'><pre> repl.<span class="hljs-literal">on</span> <span class="hljs-string">'SIGINT'</span>, <span class="hljs-function">-&gt;</span> sawSIGINT = <span class="hljs-literal">yes</span>
repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function">-&gt;</span> fs.closeSync fd</pre></div></div>
<div class="content"><div class='highlight'><pre> repl.<span class="hljs-literal">on</span> <span class="hljs-string">&#x27;SIGINT&#x27;</span>, <span class="hljs-function">-&gt;</span> sawSIGINT = <span class="hljs-literal">yes</span>
repl.<span class="hljs-literal">on</span> <span class="hljs-string">&#x27;exit&#x27;</span>, <span class="hljs-function">-&gt;</span> fs.closeSync fd</pre></div></div>
</li>
@@ -657,17 +657,17 @@ undeclared variable <code>__</code>.</p>
<li id="section-31">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-31">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-31">&#x00a7;</a>
</div>
<p>Add a command to show the history stack</p>
</div>
<div class="content"><div class='highlight'><pre> repl.commands[getCommandId(repl, <span class="hljs-string">'history'</span>)] =
help: <span class="hljs-string">'Show command history'</span>
<div class="content"><div class='highlight'><pre> repl.commands[getCommandId(repl, <span class="hljs-string">&#x27;history&#x27;</span>)] =
help: <span class="hljs-string">&#x27;Show command history&#x27;</span>
action: <span class="hljs-function">-&gt;</span>
repl.outputStream.write <span class="hljs-string">"<span class="hljs-subst">#{repl.rli.history[..].reverse().join <span class="hljs-string">'\n'</span>}</span>\n"</span>
repl.outputStream.write <span class="hljs-string">&quot;<span class="hljs-subst">#{repl.history[..].reverse().join <span class="hljs-string">&#x27;\n&#x27;</span>}</span>\n&quot;</span>
repl.displayPrompt()
<span class="hljs-function">
<span class="hljs-title">getCommandId</span> = <span class="hljs-params">(repl, commandName)</span> -&gt;</span></pre></div></div>
@@ -678,45 +678,45 @@ undeclared variable <code>__</code>.</p>
<li id="section-32">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-32">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-32">&#x00a7;</a>
</div>
<p>Node 0.11 changed API, a command such as .help is now stored as help</p>
</div>
<div class="content"><div class='highlight'><pre> commandsHaveLeadingDot = repl.commands[<span class="hljs-string">'.help'</span>]?
<span class="hljs-keyword">if</span> commandsHaveLeadingDot <span class="hljs-keyword">then</span> <span class="hljs-string">".<span class="hljs-subst">#{commandName}</span>"</span> <span class="hljs-keyword">else</span> commandName
<div class="content"><div class='highlight'><pre> commandsHaveLeadingDot = repl.commands[<span class="hljs-string">&#x27;.help&#x27;</span>]?
<span class="hljs-keyword">if</span> commandsHaveLeadingDot <span class="hljs-keyword">then</span> <span class="hljs-string">&quot;.<span class="hljs-subst">#{commandName}</span>&quot;</span> <span class="hljs-keyword">else</span> commandName
<span class="hljs-built_in">module</span>.exports =
module.<span class="hljs-built_in">exports</span> =
start: <span class="hljs-function"><span class="hljs-params">(opts = {})</span> -&gt;</span>
[major, minor, build] = process.versions.node.split(<span class="hljs-string">'.'</span>).map (n) -&gt; parseInt(n, <span class="hljs-number">10</span>)
[major, minor, build] = process.versions.node.split(<span class="hljs-string">&#x27;.&#x27;</span>).map (n) -&gt; <span class="hljs-built_in">parseInt</span>(n, <span class="hljs-number">10</span>)
<span class="hljs-keyword">if</span> major &lt; <span class="hljs-number">6</span>
<span class="hljs-built_in">console</span>.warn <span class="hljs-string">"Node 6+ required for CoffeeScript REPL"</span>
console.warn <span class="hljs-string">&quot;Node 6+ required for CoffeeScript REPL&quot;</span>
process.exit <span class="hljs-number">1</span>
CoffeeScript.register()
process.argv = [<span class="hljs-string">'coffee'</span>].concat process.argv[<span class="hljs-number">2.</span>.]
process.argv = [<span class="hljs-string">&#x27;coffee&#x27;</span>].concat process.argv[<span class="hljs-number">2.</span>.]
<span class="hljs-keyword">if</span> opts.transpile
transpile = {}
<span class="hljs-keyword">try</span>
transpile.transpile = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@babel/core'</span>).transform
transpile.transpile = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;@babel/core&#x27;</span>).transform
<span class="hljs-keyword">catch</span>
<span class="hljs-keyword">try</span>
transpile.transpile = <span class="hljs-built_in">require</span>(<span class="hljs-string">'babel-core'</span>).transform
transpile.transpile = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;babel-core&#x27;</span>).transform
<span class="hljs-keyword">catch</span>
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'''
console.error <span class="hljs-string">&#x27;&#x27;&#x27;
To use --transpile with an interactive REPL, @babel/core must be installed either in the current folder or globally:
npm install --save-dev @babel/core
or
npm install --global @babel/core
And you must save options to configure Babel in one of the places it looks to find its options.
See https://coffeescript.org/#transpilation
'''</span>
&#x27;&#x27;&#x27;</span>
process.exit <span class="hljs-number">1</span>
transpile.options =
filename: path.resolve process.cwd(), <span class="hljs-string">'&lt;repl&gt;'</span></pre></div></div>
filename: path.resolve process.cwd(), <span class="hljs-string">&#x27;&lt;repl&gt;&#x27;</span></pre></div></div>
</li>
@@ -724,8 +724,8 @@ undeclared variable <code>__</code>.</p>
<li id="section-33">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-33">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-33">&#x00a7;</a>
</div>
<p>Since the REPL compilation path is unique (in <code>eval</code> above), we need
another way to get the <code>options</code> object attached to a module so that
@@ -734,15 +734,15 @@ the REPL, the only applicable option is <code>transpile</code>.</p>
</div>
<div class="content"><div class='highlight'><pre> Module = <span class="hljs-built_in">require</span> <span class="hljs-string">'module'</span>
<div class="content"><div class='highlight'><pre> Module = <span class="hljs-built_in">require</span> <span class="hljs-string">&#x27;module&#x27;</span>
originalModuleLoad = Module::load
Module::load = <span class="hljs-function"><span class="hljs-params">(filename)</span> -&gt;</span>
@options = transpile: transpile.options
originalModuleLoad.call @, filename
opts = merge replDefaults, opts
repl = nodeREPL.start opts
runInContext opts.prelude, repl.context, <span class="hljs-string">'prelude'</span> <span class="hljs-keyword">if</span> opts.prelude
repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function">-&gt;</span> repl.outputStream.write <span class="hljs-string">'\n'</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> repl.rli.closed
runInContext opts.prelude, repl.context, <span class="hljs-string">&#x27;prelude&#x27;</span> <span class="hljs-keyword">if</span> opts.prelude
repl.<span class="hljs-literal">on</span> <span class="hljs-string">&#x27;exit&#x27;</span>, <span class="hljs-function">-&gt;</span> repl.outputStream.write <span class="hljs-string">&#x27;\n&#x27;</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> repl.closed
addMultilineHandler repl
addHistory repl, opts.historyFile, opts.historyMaxInputSize <span class="hljs-keyword">if</span> opts.historyFile</pre></div></div>
@@ -752,14 +752,14 @@ the REPL, the only applicable option is <code>transpile</code>.</p>
<li id="section-34">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-34">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-34">&#x00a7;</a>
</div>
<p>Adapt help inherited from the node REPL</p>
</div>
<div class="content"><div class='highlight'><pre> repl.commands[getCommandId(repl, <span class="hljs-string">'load'</span>)].help = <span class="hljs-string">'Load code from a file into this REPL session'</span>
<div class="content"><div class='highlight'><pre> repl.commands[getCommandId(repl, <span class="hljs-string">&#x27;load&#x27;</span>)].help = <span class="hljs-string">&#x27;Load code from a file into this REPL session&#x27;</span>
repl</pre></div></div>
</li>

File diff suppressed because it is too large Load Diff

View File

@@ -112,8 +112,8 @@
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-1">&#x00a7;</a>
</div>
<p>The <strong>Scope</strong> class regulates lexical scoping within CoffeeScript. As you
generate code, you create a tree of scopes in the same shape as the nested
@@ -124,7 +124,7 @@ with external scopes.</p>
</div>
<div class="content"><div class='highlight'><pre>exports.Scope = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Scope</span></span></pre></div></div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.Scope = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Scope</span></span></pre></div></div>
</li>
@@ -132,8 +132,8 @@ with external scopes.</p>
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-2">&#x00a7;</a>
</div>
<p>Initialize a scope with its parent, for lookups up the chain,
as well as a reference to the <strong>Block</strong> node it belongs to, which is
@@ -145,7 +145,7 @@ that should be output as part of variable declarations.</p>
</div>
<div class="content"><div class='highlight'><pre> constructor: <span class="hljs-function"><span class="hljs-params">(@parent, @expressions, @method, @referencedVars)</span> -&gt;</span>
@variables = [{name: <span class="hljs-string">'arguments'</span>, type: <span class="hljs-string">'arguments'</span>}]
@variables = [{name: <span class="hljs-string">&#x27;arguments&#x27;</span>, type: <span class="hljs-string">&#x27;arguments&#x27;</span>}]
@comments = {}
@positions = {}
@utilities = {} <span class="hljs-keyword">unless</span> @parent</pre></div></div>
@@ -156,14 +156,14 @@ that should be output as part of variable declarations.</p>
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-3">&#x00a7;</a>
</div>
<p>The <code>@root</code> is the top-level <strong>Scope</strong> object for a given file.</p>
</div>
<div class="content"><div class='highlight'><pre> @root = @parent?.root ? <span class="hljs-keyword">this</span></pre></div></div>
<div class="content"><div class='highlight'><pre> @root = @parent?.root ? this</pre></div></div>
</li>
@@ -171,8 +171,8 @@ that should be output as part of variable declarations.</p>
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-4">&#x00a7;</a>
</div>
<p>Adds a new variable or overrides an existing one.</p>
@@ -191,8 +191,8 @@ that should be output as part of variable declarations.</p>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-5">&#x00a7;</a>
</div>
<p>When <code>super</code> is called, we need to find the name of the current method were
in, so that we know how to invoke the same method of the parent class. This
@@ -212,15 +212,15 @@ function object that has a name filled in, or bottoms out.</p>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-6">&#x00a7;</a>
</div>
<p>Look up a variable name in lexical scope, and declare it if it does not
already exist.</p>
</div>
<div class="content"><div class='highlight'><pre> find: <span class="hljs-function"><span class="hljs-params">(name, type = <span class="hljs-string">'var'</span>)</span> -&gt;</span>
<div class="content"><div class='highlight'><pre> find: <span class="hljs-function"><span class="hljs-params">(name, type = <span class="hljs-string">&#x27;var&#x27;</span>)</span> -&gt;</span>
<span class="hljs-keyword">return</span> <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> @check name
@add name, type
<span class="hljs-literal">no</span></pre></div></div>
@@ -231,8 +231,8 @@ already exist.</p>
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-7">&#x00a7;</a>
</div>
<p>Reserve a variable name as originating from a function parameter for this
scope. No <code>var</code> required for internal references.</p>
@@ -241,7 +241,7 @@ scope. No <code>var</code> required for internal references.</p>
<div class="content"><div class='highlight'><pre> parameter: <span class="hljs-function"><span class="hljs-params">(name)</span> -&gt;</span>
<span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> @shared <span class="hljs-keyword">and</span> @parent.check name, <span class="hljs-literal">yes</span>
@add name, <span class="hljs-string">'param'</span></pre></div></div>
@add name, <span class="hljs-string">&#x27;param&#x27;</span></pre></div></div>
</li>
@@ -249,8 +249,8 @@ scope. No <code>var</code> required for internal references.</p>
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-8">&#x00a7;</a>
</div>
<p>Just check to see if a variable has already been declared, without reserving,
walks up to the root scope.</p>
@@ -266,8 +266,8 @@ walks up to the root scope.</p>
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-9">&#x00a7;</a>
</div>
<p>Generate a temporary variable name at the given index.</p>
@@ -276,14 +276,14 @@ walks up to the root scope.</p>
<div class="content"><div class='highlight'><pre> temporary: <span class="hljs-function"><span class="hljs-params">(name, index, single=<span class="hljs-literal">false</span>)</span> -&gt;</span>
<span class="hljs-keyword">if</span> single
startCode = name.charCodeAt(<span class="hljs-number">0</span>)
endCode = <span class="hljs-string">'z'</span>.charCodeAt(<span class="hljs-number">0</span>)
endCode = <span class="hljs-string">&#x27;z&#x27;</span>.charCodeAt(<span class="hljs-number">0</span>)
diff = endCode - startCode
newCode = startCode + index % (diff + <span class="hljs-number">1</span>)
letter = String.fromCharCode(newCode)
letter = <span class="hljs-built_in">String</span>.fromCharCode(newCode)
num = index <span class="hljs-regexp">//</span> (diff + <span class="hljs-number">1</span>)
<span class="hljs-string">"<span class="hljs-subst">#{letter}</span><span class="hljs-subst">#{num <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>}</span>"</span>
<span class="hljs-string">&quot;<span class="hljs-subst">#{letter}</span><span class="hljs-subst">#{num <span class="hljs-keyword">or</span> <span class="hljs-string">&#x27;&#x27;</span>}</span>&quot;</span>
<span class="hljs-keyword">else</span>
<span class="hljs-string">"<span class="hljs-subst">#{name}</span><span class="hljs-subst">#{index <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>}</span>"</span></pre></div></div>
<span class="hljs-string">&quot;<span class="hljs-subst">#{name}</span><span class="hljs-subst">#{index <span class="hljs-keyword">or</span> <span class="hljs-string">&#x27;&#x27;</span>}</span>&quot;</span></pre></div></div>
</li>
@@ -291,8 +291,8 @@ walks up to the root scope.</p>
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-10">&#x00a7;</a>
</div>
<p>Gets the type of a variable.</p>
@@ -308,8 +308,8 @@ walks up to the root scope.</p>
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-11">&#x00a7;</a>
</div>
<p>If we need to store an intermediate result, find an available name for a
compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…</p>
@@ -322,7 +322,7 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…
temp = @temporary name, index, options.single
<span class="hljs-keyword">break</span> <span class="hljs-keyword">unless</span> @check(temp) <span class="hljs-keyword">or</span> temp <span class="hljs-keyword">in</span> @root.referencedVars
index++
@add temp, <span class="hljs-string">'var'</span>, <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> options.reserve ? <span class="hljs-literal">true</span>
@add temp, <span class="hljs-string">&#x27;var&#x27;</span>, <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> options.reserve ? <span class="hljs-literal">true</span>
temp</pre></div></div>
</li>
@@ -331,8 +331,8 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-12">&#x00a7;</a>
</div>
<p>Ensure that an assignment is made at the top of this scope
(or at the top-level scope, if requested).</p>
@@ -349,8 +349,8 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-13">&#x00a7;</a>
</div>
<p>Does this scope have any declared variables?</p>
@@ -365,15 +365,15 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-14">&#x00a7;</a>
</div>
<p>Return the list of variables first declared in this scope.</p>
</div>
<div class="content"><div class='highlight'><pre> declaredVariables: <span class="hljs-function">-&gt;</span>
(v.name <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> @variables <span class="hljs-keyword">when</span> v.type <span class="hljs-keyword">is</span> <span class="hljs-string">'var'</span>).sort()</pre></div></div>
(v.name <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> @variables <span class="hljs-keyword">when</span> v.type <span class="hljs-keyword">is</span> <span class="hljs-string">&#x27;var&#x27;</span>).sort()</pre></div></div>
</li>
@@ -381,8 +381,8 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-15">&#x00a7;</a>
</div>
<p>Return the list of assignments that are supposed to be made at the top
of this scope.</p>
@@ -390,7 +390,7 @@ of this scope.</p>
</div>
<div class="content"><div class='highlight'><pre> assignedVariables: <span class="hljs-function">-&gt;</span>
<span class="hljs-string">"<span class="hljs-subst">#{v.name}</span> = <span class="hljs-subst">#{v.type.value}</span>"</span> <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> @variables <span class="hljs-keyword">when</span> v.type.assigned</pre></div></div>
<span class="hljs-string">&quot;<span class="hljs-subst">#{v.name}</span> = <span class="hljs-subst">#{v.type.value}</span>&quot;</span> <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> @variables <span class="hljs-keyword">when</span> v.type.assigned</pre></div></div>
</li>

View File

@@ -112,8 +112,8 @@
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-1">&#x00a7;</a>
</div>
<p>Source maps allow JavaScript runtimes to match running JavaScript back to
the original source code that corresponds to it. This can be minified
@@ -134,8 +134,8 @@ of this information — to write out alongside the generated JavaScript.</p>
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-2">&#x00a7;</a>
</div>
<p>A <strong>LineMap</strong> object keeps track of information about original line and column
positions for a single line of output JavaScript code.
@@ -161,8 +161,8 @@ positions for a single line of output JavaScript code.
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-3">&#x00a7;</a>
</div>
<h2 id="sourcemap">SourceMap</h2>
@@ -174,8 +174,8 @@ positions for a single line of output JavaScript code.
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-4">&#x00a7;</a>
</div>
<p>Maps locations in a single generated JavaScript file back to locations in
the original CoffeeScript source file.</p>
@@ -195,8 +195,8 @@ through the arrays of line and column buffer to produce it.</p>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-5">&#x00a7;</a>
</div>
<p>Adds a mapping to this SourceMap. <code>sourceLocation</code> and <code>generatedLocation</code>
are both <code>[line, column]</code> arrays. If <code>options.noReplace</code> is true, then if there
@@ -216,8 +216,8 @@ effect.</p>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-6">&#x00a7;</a>
</div>
<p>Look up the original position of a given <code>line</code> and <code>column</code> in the generated
code.</p>
@@ -234,10 +234,10 @@ code.</p>
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-7">&#x00a7;</a>
</div>
<h2 id="v3-sourcemap-generation">V3 SourceMap Generation</h2>
<h2 id="caching">Caching</h2>
</div>
@@ -247,8 +247,45 @@ code.</p>
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-8">&#x00a7;</a>
</div>
<p>A static source maps cache <code>filename</code>: <code>map</code>. These are used for transforming
stack traces and are currently set in <code>CoffeeScript.compile</code> for all files
compiled with the source maps option.</p>
</div>
<div class="content"><div class='highlight'><pre> @sourceMaps: <span class="hljs-built_in">Object</span>.create <span class="hljs-literal">null</span>
@registerCompiled: <span class="hljs-function"><span class="hljs-params">(filename, source, sourcemap)</span> =&gt;</span>
<span class="hljs-keyword">if</span> sourcemap?
@sourceMaps[filename] = sourcemap
@getSourceMap: <span class="hljs-function"><span class="hljs-params">(filename)</span> =&gt;</span>
@sourceMaps[filename]</pre></div></div>
</li>
<li id="section-9">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-9">&#x00a7;</a>
</div>
<h2 id="v3-sourcemap-generation">V3 SourceMap Generation</h2>
</div>
</li>
<li id="section-10">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-10">&#x00a7;</a>
</div>
<p>Builds up a V3 source map, returning the generated JSON as a string.
<code>options.sourceRoot</code> may be used to specify the sourceRoot written to the source
@@ -263,41 +300,41 @@ set “sources” and “file”, respectively.</p>
lastSourceLine = <span class="hljs-number">0</span>
lastSourceColumn = <span class="hljs-number">0</span>
needComma = <span class="hljs-literal">no</span>
buffer = <span class="hljs-string">""</span>
buffer = <span class="hljs-string">&quot;&quot;</span>
<span class="hljs-keyword">for</span> lineMap, lineNumber <span class="hljs-keyword">in</span> @lines <span class="hljs-keyword">when</span> lineMap
<span class="hljs-keyword">for</span> mapping <span class="hljs-keyword">in</span> lineMap.columns <span class="hljs-keyword">when</span> mapping
<span class="hljs-keyword">while</span> writingline &lt; mapping.line
lastColumn = <span class="hljs-number">0</span>
needComma = <span class="hljs-literal">no</span>
buffer += <span class="hljs-string">";"</span>
buffer += <span class="hljs-string">&quot;;&quot;</span>
writingline++</pre></div></div>
</li>
<li id="section-9">
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-11">&#x00a7;</a>
</div>
<p>Write a comma if weve already written a segment on this line.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> needComma
buffer += <span class="hljs-string">","</span>
buffer += <span class="hljs-string">&quot;,&quot;</span>
needComma = <span class="hljs-literal">no</span></pre></div></div>
</li>
<li id="section-10">
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-12">&#x00a7;</a>
</div>
<p>Write the next segment. Segments can be 1, 4, or 5 values. If just one, then it
is a generated column which doesnt match anything in the source code.</p>
@@ -312,11 +349,11 @@ column for the current line:</p>
</li>
<li id="section-11">
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-13">&#x00a7;</a>
</div>
<p>The index into the list of sources:</p>
@@ -327,11 +364,11 @@ column for the current line:</p>
</li>
<li id="section-12">
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-14">&#x00a7;</a>
</div>
<p>The starting line in the original source, relative to the previous source line.</p>
@@ -343,11 +380,11 @@ column for the current line:</p>
</li>
<li id="section-13">
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-15">&#x00a7;</a>
</div>
<p>The starting column in the original source, relative to the previous column.</p>
@@ -360,11 +397,11 @@ column for the current line:</p>
</li>
<li id="section-14">
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-16">&#x00a7;</a>
</div>
<p>Produce the canonical JSON object format for a “v3” source map.</p>
@@ -375,12 +412,12 @@ column for the current line:</p>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> options.filename
[options.filename]
<span class="hljs-keyword">else</span>
[<span class="hljs-string">'&lt;anonymous&gt;'</span>]
[<span class="hljs-string">&#x27;&lt;anonymous&gt;&#x27;</span>]
v3 =
version: <span class="hljs-number">3</span>
file: options.generatedFile <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>
sourceRoot: options.sourceRoot <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>
file: options.generatedFile <span class="hljs-keyword">or</span> <span class="hljs-string">&#x27;&#x27;</span>
sourceRoot: options.sourceRoot <span class="hljs-keyword">or</span> <span class="hljs-string">&#x27;&#x27;</span>
sources: sources
names: []
mappings: buffer
@@ -392,11 +429,11 @@ column for the current line:</p>
</li>
<li id="section-15">
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-17">&#x00a7;</a>
</div>
<h2 id="base64-vlq-encoding">Base64 VLQ Encoding</h2>
@@ -405,11 +442,11 @@ column for the current line:</p>
</li>
<li id="section-16">
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-18">&#x00a7;</a>
</div>
<p>Note that SourceMap VLQ encoding is “backwards”. MIDI-style VLQ encoding puts
the most-significant-bit (MSB) from the original value into the MSB of the VLQ
@@ -424,16 +461,16 @@ bits of the original value encoded into the first byte of the VLQ encoded value.
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - <span class="hljs-number">1</span> <span class="hljs-comment"># 0001 1111</span>
encodeVlq: <span class="hljs-function"><span class="hljs-params">(value)</span> -&gt;</span>
answer = <span class="hljs-string">''</span></pre></div></div>
answer = <span class="hljs-string">&#x27;&#x27;</span></pre></div></div>
</li>
<li id="section-17">
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-19">&#x00a7;</a>
</div>
<p>Least significant bit represents the sign.</p>
@@ -444,26 +481,26 @@ bits of the original value encoded into the first byte of the VLQ encoded value.
</li>
<li id="section-18">
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-20">&#x00a7;</a>
</div>
<p>The next bits are the actual value.</p>
</div>
<div class="content"><div class='highlight'><pre> valueToEncode = (Math.abs(value) &lt;&lt; <span class="hljs-number">1</span>) + signBit</pre></div></div>
<div class="content"><div class='highlight'><pre> valueToEncode = (<span class="hljs-built_in">Math</span>.abs(value) &lt;&lt; <span class="hljs-number">1</span>) + signBit</pre></div></div>
</li>
<li id="section-19">
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-21">&#x00a7;</a>
</div>
<p>Make sure we encode at least one character, even if valueToEncode is 0.</p>
@@ -480,11 +517,11 @@ bits of the original value encoded into the first byte of the VLQ encoded value.
</li>
<li id="section-20">
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-22">&#x00a7;</a>
</div>
<h2 id="regular-base64-encoding">Regular Base64 Encoding</h2>
@@ -493,34 +530,34 @@ bits of the original value encoded into the first byte of the VLQ encoded value.
</li>
<li id="section-21">
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-23">&#x00a7;</a>
</div>
</div>
<div class="content"><div class='highlight'><pre> BASE64_CHARS = <span class="hljs-string">'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'</span>
<div class="content"><div class='highlight'><pre> BASE64_CHARS = <span class="hljs-string">&#x27;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&#x27;</span>
encodeBase64: <span class="hljs-function"><span class="hljs-params">(value)</span> -&gt;</span>
BASE64_CHARS[value] <span class="hljs-keyword">or</span> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Error <span class="hljs-string">"Cannot Base64 encode value: <span class="hljs-subst">#{value}</span>"</span></pre></div></div>
BASE64_CHARS[value] <span class="hljs-keyword">or</span> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span> <span class="hljs-string">&quot;Cannot Base64 encode value: <span class="hljs-subst">#{value}</span>&quot;</span></pre></div></div>
</li>
<li id="section-22">
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
<div class="sswrap ">
<a class="ss" href="#section-24">&#x00a7;</a>
</div>
<p>Our API for source maps is just the <code>SourceMap</code> class.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">module</span>.exports = SourceMap</pre></div></div>
<div class="content"><div class='highlight'><pre>module.<span class="hljs-built_in">exports</span> = SourceMap</pre></div></div>
</li>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
# Your browser must support dynamic import to run this example.
do ->
{ run } = await import('./browser-compiler-modern/coffeescript.js')
run '''
if 5 < new Date().getHours() < 9
alert 'Time to make the coffee!'
else
alert 'Time to get some work done.'
'''

View File

@@ -1,5 +1,5 @@
import 'local-file.coffee'
import 'coffeescript'
import './local-file.js' # Must be the filename of the generated file
import 'package'
import _ from 'underscore'
import * as underscore from 'underscore'
@@ -9,6 +9,8 @@ import { now as currentTimestamp } from 'underscore'
import { first, last } from 'underscore'
import utilityBelt, { each } from 'underscore'
import dates from './calendar.json' assert { type: 'json' }
export default Math
export square = (x) -> x * x
export class Mathematics
@@ -20,3 +22,4 @@ export { Mathematics as default, sqrt as squareRoot }
export * from 'underscore'
export { max, min } from 'underscore'
export { version } from './package.json' assert { type: 'json' }

View File

@@ -3,4 +3,4 @@ releaseHeader('2010-02-25', '0.5.2', '0.5.1')
```
Added a compressed version of the compiler for inclusion in web pages as
`/v<%= majorVersion %>/browser-compiler/coffeescript.js`. Itll automatically run any script tags with type `text/coffeescript` for you. Added a `--stdio` option to the `coffee` command, for piped-in compiles.
`/v<%= majorVersion %>/browser-compiler-legacy/coffeescript.js`. Itll automatically run any script tags with type `text/coffeescript` for you. Added a `--stdio` option to the `coffee` command, for piped-in compiles.

View File

@@ -2,7 +2,7 @@
releaseHeader('2017-09-02', '2.0.0-beta5', '2.0.0-beta4')
```
* Node 6 is now supported, and we will try to maintain that as the minimum required version for CoffeeScript 2 via the `coffee` command or Node API. Older versions of Node, or non-evergreen browsers, can compile via the [browser compiler](./browser-compiler/coffeescript.js).
* Node 6 is now supported, and we will try to maintain that as the minimum required version for CoffeeScript 2 via the `coffee` command or Node API. Older versions of Node, or non-evergreen browsers, can compile via the [legacy browser compiler](./browser-compiler-legacy/coffeescript.js).
* The command line `--output` flag now allows you to specify an output filename, not just an output folder.
* The command line `--require` flag now properly handles filenames or module names that are invalid identifiers (like an NPM module with a hyphen in the name).
* `Object.assign`, output when object destructuring is used, is polyfilled using the same polyfill that Babel outputs. This means that polyfills shouldnt be required unless support for Internet Explorer 8 or below is desired (or your own code uses a feature that requires a polyfill). See [ES2015+ Output](#es2015plus-output).

View File

@@ -0,0 +1,8 @@
```
releaseHeader('2019-03-29', '2.4.0', '2.3.2')
```
* Dynamic `import()` expressions are now supported. The parentheses are always required, to distinguish from `import` statements. See [Modules](#dynamic-import). Note that as of this writing, the JavaScript feature itself is still Stage 3; if it changes before being fully standardized, it may change in CoffeeScript too. Using `import()` before its upstream [ECMAScript proposal](https://github.com/tc39/proposal-dynamic-import) is finalized should be considered provisional, subject to breaking changes if the proposal changes or is rejected. We have also revised our [policy](#contributing) on Stage 3 ECMAScript features, to support them when the features are [shipped](https://caniuse.com/#feat=es6-module-dynamic-import) in significant runtimes such as major browsers or Node.js.
* There are now two browser versions of the CoffeeScript compiler: the traditional one thats been published for years, and a new [ES module version](/browser-compiler-modern/coffeescript.js) that can be used via `import`. If your browser supports it, it is in effect on this page. A reference to the ES module browser compiler is in the `package.json` `"module"` field.
* The Node API now exposes the previously private `registerCompiled` method, to allow plugins that use the `coffeescript` package to take advantage of CoffeeScripts internal caching.
* Bugfixes for commas in strings in block arrays, a reference to `@` not being maintained in a `do` block in a class, and function default parameters should no longer be wrapped by extraneous parentheses.

View File

@@ -0,0 +1,5 @@
```
releaseHeader('2019-04-08', '2.4.1', '2.4.0')
```
* Both the [traditional ES5](/browser-compiler-legacy/coffeescript.js) and [modern ES module](/browser-compiler-modern/coffeescript.js) versions of the CoffeeScript browser compiler are now published to NPM, enabling the browser compilers use via services that provide NPM modules code available via public CDN. The traditional version is referenced via the `package.json` `"browser"` field, and the ES module version via the `"module"` field.

View File

@@ -0,0 +1,11 @@
```
releaseHeader('2019-12-31', '2.5.0', '2.4.1')
```
* The compiler now supports a new `ast` option, available via `--ast` on the command line or `ast` via the Node API. This option outputs an “abstract syntax tree,” or a JSON-like representation of the input CoffeeScript source code. This AST follows [Babels spec](https://github.com/babel/babel/blob/master/packages/babel-parser/ast/spec.md) as closely as possible, for compatibility with tools that work with JavaScript source code. Two tools that use this new AST output are [`eslint-plugin-coffee`](https://github.com/helixbass/eslint-plugin-coffee), a plugin to lint CoffeeScript via [ESLint](https://eslint.org/); and [`prettier-plugin-coffeescript`](https://github.com/helixbass/prettier-plugin-coffeescript), a plugin to reformat CoffeeScript source code via [Prettier](https://prettier.io/). _The structure and properties of CoffeeScripts AST are not final and may undergo breaking changes between CoffeeScript versions; please [open an issue](https://github.com/jashkenas/coffeescript/issues) if you are interested in creating new integrations._
* [Numeric separators](https://github.com/tc39/proposal-numeric-separator) are now supported in CoffeeScript, following the same syntax as JavaScript: `1_234_567`.
* [`BigInt` numbers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) are now supported in CoffeeScript, following the same syntax as JavaScript: `42n`.
* `'''` and `"""` strings are now output as more readable JavaScript template literals, or backtick (`` ` ``) strings, with actual newlines rather than `\n` escape sequences.
* Classes can now contain computed properties, e.g. `[someVar]: ->` or `@[anotherVar]: ->`.
* JSX tags can now contain XML-style namespaces, e.g. `<image xlink:href="data:image/png" />` or `<Something:Tag></Something:Tag>`.
* Bugfixes for comments after colons not appearing the output; reserved words mistakenly being disallowed as JSX attributes; indented leading elisions in multiline arrays; and invalid location data in source maps.

View File

@@ -0,0 +1,7 @@
```
releaseHeader('2020-01-31', '2.5.1', '2.5.0')
```
* Object splats can now include prototype shorthands, such as `a = {b::c...}`; and soaks, such as `a = {b?.c..., d?()...}`.
* Bugfix for regression in 2.5.0 where compilation became much slower for files with Windows-style line endings.
* Bugfix for an implicit object after a line continuation keyword like `or` inside a larger implicit object.

View File

@@ -0,0 +1,7 @@
```
releaseHeader('2021-09-19', '2.6.0', '2.5.1')
```
* The syntax `import.meta`, including `import.meta.url`, is now supported.
* The `await` keyword is now supported outside of functions (in other words, at the top level). [Note that JavaScript runtimes only support this for ES modules.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#top_level_await)
* Bugfix for a `for` comprehension at the end of an `unless` or `until` line.

View File

@@ -0,0 +1,6 @@
```
releaseHeader('2021-10-03', '2.6.1', '2.6.0')
```
* The `coffeescript` package itself now supports named exports when used by ES modules in Node.js; or in other words, `import { compile } from 'coffeescript'` now works, rather than only `import CoffeeScript from 'coffeescript'`.
* Bugfix for a stack overflow error when compiling large files in non-bare mode.

View File

@@ -0,0 +1,8 @@
```
releaseHeader('2022-04-23', '2.7.0', '2.6.1')
```
* The [import assertions syntax](https://github.com/tc39/proposal-import-assertions) is now supported. This allows statements like `export { version } from './package.json' assert { type: 'json' }` or expressions like `import('./calendar.json', { assert { type: 'json' } })`.
* CoffeeScript no longer always patches Nodes error stack traces. This patching, where the line and column numbers are adjusted to match the source CoffeeScript rather than the generated JavaScript, caused conflicts with other libraries and is unnecessary when Nodes new [`--enable-source-maps` flag](https://nodejs.org/docs/latest/api/cli.html#--enable-source-maps) is passed. The patching will now occur only when `--enable-source-maps` is not set, no other library has already patched the stack traces, and `require('coffeescript/register')` is used. The patching can be enabled explicitly via `require('coffeescript').patchStackTrace()` or `import { patchStackTrace } from 'coffeescript'; patchStackTrace()`.
* Bugfix for an issue where block (triple-quoted) strings werent getting transpiled correctly into a JSX expression container wrapping the template literal (such as ``<div a={`...`} />``).
* Bugfixes for line continuations not behaving as expected for a nonempty first line of an explicit `[` array or `{` object literal.

View File

@@ -12,13 +12,14 @@ Once installed, you should have access to the `coffee` command, which can execut
| `-o, --output [DIR]` | Write out all compiled JavaScript files into the specified directory. Use in conjunction with `--compile` or `--watch`. |
| `-w, --watch` | Watch files for changes, rerunning the specified command when any file is updated. |
| `-p, --print` | Instead of writing out the JavaScript as a file, print it directly to **stdout**. |
| `-s, --stdio` | Pipe in CoffeeScript to STDIN and get back JavaScript over STDOUT. Good for use with processes written in other languages. An example:<br>`cat src/cake.coffee | coffee -sc` |
| `-s, --stdio` | Pipe in CoffeeScript to STDIN and get back JavaScript over STDOUT. Good for use with processes written in other languages. An example:<br><code>cat src/cake.coffee &#124; coffee -sc</code> |
| `-l, --literate` | Parses the code as Literate CoffeeScript. You only need to specify this when passing in code directly over **stdio**, or using some sort of extension-less file name. |
| `-e, --eval` | Compile and print a little snippet of CoffeeScript directly from the command line. For example:<br>`coffee -e "console.log num for num in [10..1]"` |
| `-r, --require [MODULE]`&emsp; | `require()` the given module before starting the REPL or evaluating the code given with the `--eval` flag. |
| `-b, --bare` | Compile the JavaScript without the [top-level function safety wrapper](#lexical-scope). |
| `--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. |
| `--ast` | Generate an abstract syntax tree of nodes of the CoffeeScript. Used for integrating with JavaScript build tools. |
| `--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. |

View File

@@ -2,9 +2,12 @@
Most modern JavaScript features that CoffeeScript supports can run natively in Node 7.6+, meaning that Node can run CoffeeScripts output without any further processing required. Here are some notable exceptions:
* [Modules](#modules) and [JSX](#jsx) always require transpilation.
* [JSX](#jsx) always requires transpilation.
* [Splats, a.k.a. object rest/spread syntax, for objects](https://coffeescript.org/#splats) are supported by Node 8.6+.
* The [regular expression `s` (dotall) flag](https://github.com/tc39/proposal-regexp-dotall-flag) is supported by Node 9+.
* [Async generator functions](https://github.com/tc39/proposal-async-iteration) are supported by Node 10+.
* [Modules](#modules) are supported by Node 12+ with `"type": "module"` in your projects `package.json`.
This list may be incomplete, and excludes versions of Node that support newer features behind flags; please refer to [node.green](http://node.green/) for full details. You can [run the tests in your browser](test.html) to see what your browser supports. It is your responsibility to ensure that your runtime supports the modern features you use; or that you [transpile](#transpilation) your code. When in doubt, transpile.
For compatibility with other JavaScript frameworks and tools, see [Integrations](#integrations).

View File

@@ -2,7 +2,7 @@
Contributions are welcome! Feel free to fork [the repo](https://github.com/jashkenas/coffeescript) and submit a pull request.
[Some features of ECMAScript are intentionally unsupported](#unsupported). Please review both the open and closed [issues on GitHub](https://github.com/jashkenas/coffeescript/issues) to see if the feature youre looking for has already been discussed. As a general rule, we dont support ECMAScript syntax for features that arent yet finalized (at Stage 4 in the proposal approval process).
[Some features of ECMAScript are intentionally unsupported](#unsupported). Please review both the open and closed [issues on GitHub](https://github.com/jashkenas/coffeescript/issues) to see if the feature youre looking for has already been discussed. As a general rule, we dont support ECMAScript syntax for features that arent yet finalized (at Stage 4 in the [proposal approval process](https://github.com/tc39/proposals)) or implemented in major browsers and/or Node (which can sometimes happen for features in Stage 3). Any Stage 3 features that CoffeeScript chooses to support should be considered experimental, subject to breaking changes or removal until the feature reaches Stage 4.
For more resources on adding to CoffeeScript, please see [the Wiki](https://github.com/jashkenas/coffeescript/wiki/%5BHowto%5D-Hacking-on-the-CoffeeScript-Compiler), especially [How The Parser Works](https://github.com/jashkenas/coffeescript/wiki/%5BHowTo%5D-How-parsing-works).
@@ -10,7 +10,7 @@ There are several things you can do to increase your odds of having your pull re
* Create tests! Any pull request should probably include basic tests to verify you didnt break anything, or future changes wont break your code.
* Follow the style of the rest of the CoffeeScript codebase.
* Ensure any ECMAScript syntax is mature (at Stage 4), with no further potential changes.
* Ensure any ECMAScript syntax is mature (at Stage 4, or at Stage 3 with support in major browsers or runtimes).
* Add only features that have broad utility, rather than a feature aimed at a specific use case or framework.
Of course, its entirely possible that you have a great addition, but it doesnt fit within these constraints. Feel free to roll your own solution; you will have [plenty of company](https://github.com/jashkenas/coffeescript/wiki/In-The-Wild).

View File

@@ -1,6 +1,6 @@
## Installation
The command-line version of `coffee` is available as a [Node.js](https://nodejs.org/) utility, requiring Node 6 or later. The [core compiler](/v<%= majorVersion %>/browser-compiler/coffeescript.js) however, does not depend on Node, and can be run in any JavaScript environment, or in the browser (see [Try CoffeeScript](#try)).
The command-line version of `coffee` is available as a [Node.js](https://nodejs.org/) utility, requiring Node 6 or later. The [core compiler](/v<%= majorVersion %>/browser-compiler-modern/coffeescript.js) however, does not depend on Node, and can be run in any JavaScript environment, or in the browser (see [Try CoffeeScript](#try)).
To install, first make sure you have a working copy of the latest stable version of [Node.js](https://nodejs.org/). You can then install CoffeeScript globally with [npm](https://www.npmjs.com/):

View File

@@ -0,0 +1,3 @@
## Integrations
CoffeeScript is part of the vast JavaScript ecosystem, and many libraries help integrate CoffeeScript with JavaScript. Major projects, especially projects updated to work with CoffeeScript 2, are listed here; more can be found in the [wiki pages](https://github.com/jashkenas/coffeescript/wiki). If theres a project that you feel should be added to this section, please open an issue or [pull request](https://github.com/jashkenas/coffeescript/wiki/%5BHowTo%5D-Update-the-docs). Projects are listed in alphabetical order by category.

View File

@@ -0,0 +1,13 @@
### Build Tools
* [Browserify](http://browserify.org) with [coffeeify](https://github.com/jnordberg/coffeeify)
* [Grunt](https://gruntjs.com) with [grunt-contrib-coffee](https://github.com/gruntjs/grunt-contrib-coffee)
* [Gulp](https://gulpjs.com) with [gulp-coffee](https://github.com/gulp-community/gulp-coffee)
* [Parcel](https://parceljs.org) with [transformer-coffeescript](https://github.com/parcel-bundler/parcel/tree/v2/packages/transformers/coffeescript)
* [Rollup](https://rollupjs.org) with [rollup-plugin-coffee-script](https://github.com/lautis/rollup-plugin-coffee-script)
* [Webpack](https://webpack.js.org) with [coffee-loader](https://github.com/webpack-contrib/coffee-loader)

View File

@@ -0,0 +1,7 @@
### Code Editors
* [Atom](https://atom.io) [packages](https://atom.io/packages/search?q=coffeescript)
* [Sublime Text](https://sublimetext.com) [packages](https://packagecontrol.io/search/coffeescript)
* [Visual Studio Code](https://code.visualstudio.com) [extensions](https://marketplace.visualstudio.com/search?target=VSCode&term=coffeescript)

View File

@@ -0,0 +1,6 @@
### Frameworks
* [Ember](https://emberjs.com)
with [ember-cli-coffeescript](https://github.com/kimroen/ember-cli-coffeescript)
* [Meteor](https://meteor.com) with [coffeescript-compiler](https://atmospherejs.com/meteor/coffeescript-compiler)

View File

@@ -0,0 +1,7 @@
### Linters and Formatting
* [CoffeeLint](https://coffeelint.github.io/)
* [ESLint](https://eslint.org) with [eslint-plugin-coffee](https://github.com/helixbass/eslint-plugin-coffee)
* [Prettier](https://prettier.io) with [prettier-plugin-coffeescript](https://github.com/helixbass/prettier-plugin-coffeescript)

View File

@@ -0,0 +1,3 @@
### Testing
* [Jest](https://jestjs.io) with [jest-preset-coffeescript](https://github.com/danielbayley/jest-preset-coffeescript)

View File

@@ -4,7 +4,7 @@ _This reference is structured so that it can be read from top to bottom, if you
_Many of the examples can be run (where it makes sense) by pressing the_ <small>▶</small> _button on the right. The CoffeeScript on the left is editable, and the JavaScript will update as you edit._
First, the basics: CoffeeScript uses significant whitespace to delimit blocks of code. You dont need to use semicolons `;` to terminate expressions, ending the line will do just as well (although semicolons can still be used to fit multiple expressions onto a single line). Instead of using curly braces `{ }` to surround blocks of code in [functions](#literals), [if-statements](#conditionals), [switch](#switch), and [try/catch](#try), use indentation.
First, the basics: CoffeeScript uses significant whitespace to delimit blocks of code. You dont need to use semicolons `;` to terminate expressions, ending the line will do just as well (although semicolons can still be used to fit multiple expressions onto a single line). Instead of using curly braces `{ }` to surround blocks of code in [functions](#literals), [if-statements](#conditionals), [switch](#switch), and [try/catch](#try-catch), use indentation.
You dont need to use parentheses to invoke a function if youre passing arguments. The implicit call wraps forward to the end of the line or block expression.<br>
`console.log sys.inspect object``console.log(sys.inspect(object));`

View File

@@ -1,13 +1,21 @@
## Modules
ES2015 modules are supported in CoffeeScript, with very similar `import` and `export` syntax:
[ES2015 modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) are supported in CoffeeScript, with very similar `import` and `export` syntax:
```
codeFor('modules')
```
<div id="dynamic-import" class="bookmark"></div>
[Dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports) is also supported, with mandatory parentheses:
```
codeFor('dynamic_import', true)
```
<div id="modules-note" class="bookmark"></div>
Note that the CoffeeScript compiler **does not resolve modules**; writing an `import` or `export` statement in CoffeeScript will produce an `import` or `export` statement in the resulting output. It is your responsibility to [transpile](#transpilation) this ES2015 syntax into code that will work in your target runtimes.
Note that the CoffeeScript compiler **does not resolve modules**; writing an `import` or `export` statement in CoffeeScript will produce an `import` or `export` statement in the resulting output. Such statements can be run by all modern browsers (when the script is referenced via `<script type="module">`) and [by Node.js](https://nodejs.org/api/esm.html#esm_enabling) when the output `.js` files are in a folder where the nearest parent `package.json` file contains `"type": "module"`. Because the runtime is evaluating the generated output, the `import` statements must reference the output files; so if `file.coffee` is output as `file.js`, it needs to be referenced as `file.js` in the `import` statement, with the `.js` extension included.
Also note that any file with an `import` or `export` statement will be output without a [top-level function safety wrapper](#lexical-scope); in other words, importing or exporting modules will automatically trigger [bare](#usage) mode for that file. This is because per the ES2015 spec, `import` or `export` statements must occur at the topmost scope.
Also, any file with an `import` or `export` statement will be output without a [top-level function safety wrapper](#lexical-scope); in other words, importing or exporting modules will automatically trigger [bare](#usage) mode for that file. This is because per the ES2015 spec, `import` or `export` statements must occur at the topmost scope.

View File

@@ -23,4 +23,5 @@ The `compile` method has the signature `compile(code, options)` where `code` is
* `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](#lexical-scope).
* `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](http://babeljs.io/docs/usage/api/#options). See [Transpilation](#transpilation).
* `options.transpile`, **object**: if set, this must be an object with the [options to pass to Babel](http://babeljs.io/docs/usage/api/#options). See [Transpilation](#transpilation).
* `options.ast`, boolean: if true, return an abstract syntax tree of the input CoffeeScript source code.

View File

@@ -6,7 +6,7 @@ The CoffeeScript literals for objects and arrays look very similar to their Java
codeFor('objects_and_arrays', 'song.join(" … ")')
```
CoffeeScript has a shortcut for creating objects when you want the key to be set with a variable of the same name.
CoffeeScript has a shortcut for creating objects when you want the key to be set with a variable of the same name. Note that the `{` and `}` are required for this shorthand.
```
codeFor('objects_shorthand')

View File

@@ -32,7 +32,7 @@ All together now:
| `isnt` | `!==` |
| `not` | `!` |
| `and` | `&&` |
| `or` | `||` |
| `or` | <code>&#124;&#124;</code> |
| `true`, `yes`, `on` | `true` |
| `false`, `no`, `off`&emsp; | `false` |
| `@`, `this` | `this` |

View File

@@ -6,7 +6,7 @@
* [CoffeeScript Google Group](https://groups.google.com/forum/#!forum/coffeescript)<br>
If youd like to ask a question, the mailing list is a good place to get help.
* [The CoffeeScript Wiki](https://github.com/jashkenas/coffeescript/wiki)<br>
If youve ever learned a neat CoffeeScript tip or trick, or ran into a gotcha — share it on the wiki. The wiki also serves as a directory of handy [text editor extensions](https://github.com/jashkenas/coffeescript/wiki/Text-editor-plugins), [web framework plugins](https://github.com/jashkenas/coffeescript/wiki/Web-framework-plugins), and general [CoffeeScript build tools](https://github.com/jashkenas/coffeescript/wiki/Build-tools).
If youve ever learned a neat CoffeeScript tip or trick, or ran into a gotcha — share it on the wiki.
* [The FAQ](https://github.com/jashkenas/coffeescript/wiki/FAQ)<br>
Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
* [JS2Coffee](http://js2.coffee/)<br>

View File

@@ -1,5 +1,5 @@
## `"text/coffeescript"` Script Tags
While its not recommended for serious use, CoffeeScripts may be included directly within the browser using `<script type="text/coffeescript">` tags. The source includes a compressed and minified version of the compiler ([Download current version here, 51k when gzipped](/v<%= majorVersion %>/browser-compiler/coffeescript.js)) as `docs/v<%= majorVersion %>/browser-compiler/coffeescript.js`. Include this file on a page with inline CoffeeScript tags, and it will compile and evaluate them in order.
While its not recommended for serious use, CoffeeScripts may be included directly within the browser using `<script type="text/coffeescript">` tags. The source includes a compressed and minified version of the compiler ([Download current version here, 77k when gzipped](/v<%= majorVersion %>/browser-compiler-legacy/coffeescript.js)) as `docs/v<%= majorVersion %>/browser-compiler-legacy/coffeescript.js`. Include this file on a page with inline CoffeeScript tags, and it will compile and evaluate them in order.
The usual caveats about CoffeeScript apply — your inline scripts will run within a closure wrapper, so if you want to expose global variables or functions, attach them to the `window` object.

View File

@@ -1,6 +1,6 @@
### Transpilation
CoffeeScript 2 generates JavaScript that uses the latest, modern syntax. The runtime or browsers where you want your code to run [might not support all of that syntax](#compatibility). In that 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](http://babeljs.io/), [Bublé](https://buble.surge.sh/) or [Traceur Compiler](https://github.com/google/traceur-compiler).
CoffeeScript 2 generates JavaScript that uses the latest, modern syntax. The runtime or browsers where you want your code to run [might not support all of that syntax](#compatibility). In that 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](http://babeljs.io/), [Bublé](https://buble.surge.sh/) or [Traceur Compiler](https://github.com/google/traceur-compiler). See [Build Tools](#build-tools).
#### Quickstart

View File

@@ -105,7 +105,7 @@
<section id="switch">
<%= htmlFor('switch') %>
</section>
<section id="try">
<section id="try-catch">
<%= htmlFor('try') %>
</section>
<section id="comparisons">
@@ -142,6 +142,24 @@
<section id="scripts">
<%= htmlFor('scripts') %>
</section>
<section id="integrations">
<%= htmlFor('integrations') %>
<section id="build-tools">
<%= htmlFor('integrations_build_tools') %>
</section>
<section id="code-editors">
<%= htmlFor('integrations_code_editors') %>
</section>
<section id="frameworks">
<%= htmlFor('integrations_frameworks') %>
</section>
<section id="linters-and-formatting">
<%= htmlFor('integrations_linters_and_formatting') %>
</section>
<section id="testing">
<%= htmlFor('integrations_testing') %>
</section>
</section>
<section id="resources">
<%= htmlFor('resources') %>
<section id="books">
@@ -207,6 +225,27 @@
</section>
<section id="changelog">
<%= htmlFor('changelog') %>
<section id="2.7.0">
<%= htmlFor('changelog/2.7.0') %>
</section>
<section id="2.6.1">
<%= htmlFor('changelog/2.6.1') %>
</section>
<section id="2.6.0">
<%= htmlFor('changelog/2.6.0') %>
</section>
<section id="2.5.1">
<%= htmlFor('changelog/2.5.1') %>
</section>
<section id="2.5.0">
<%= htmlFor('changelog/2.5.0') %>
</section>
<section id="2.4.1">
<%= htmlFor('changelog/2.4.1') %>
</section>
<section id="2.4.0">
<%= htmlFor('changelog/2.4.0') %>
</section>
<section id="2.3.2">
<%= htmlFor('changelog/2.3.2') %>
</section>

View File

@@ -14,6 +14,8 @@ window.gtag 'config', window.GA_TRACKING_ID
# Initialize the CoffeeScript docs interactions
$(document).ready ->
CoffeeScript.patchStackTrace()
# Format dates for the users locale, e.g. 'December 24, 2009' or '24 décembre 2009'
$('time').each (index, el) ->
date = el.dateTime or $(el).text()
@@ -105,11 +107,17 @@ $(document).ready ->
if window.localStorage?
window.localStorage.setItem 'tryCoffeeScriptCode', coffee
catch exception
output = CoffeeScript.compile coffee, bare: yes
js = CoffeeScript.compile coffee, bare: yes, inlineMap: true
# Inline map is added to adjust stack trace line numbers but we strip it from the displayed JS for visual clarity.
output = js.replace /(\n\/\/# [^\n]*){2}$/, ""
lastCompilationElapsedTime = Math.max(200, Date.now() - lastCompilationStartTime)
catch exception
output = "#{exception}"
editors[index + 1].js = js
editors[index + 1].setValue output
gtag 'event', 'edit_code',
event_category: 'engagement'
event_label: $textarea.closest('[data-example]').data('example')
@@ -149,7 +157,7 @@ $(document).ready ->
run = $(@).data 'run'
index = $("##{$(@).data('example')}-js").data 'index'
js = if editors[index]?
editors[index].getValue()
editors[index].js
else
$(textareas[index]).val()
js = "#{js}\nalert(#{unescape run});" unless run is yes

View File

@@ -8,6 +8,7 @@
<div class="navbar-nav mr-auto d-none d-lg-flex">
<a href="#try" id="try-link" class="nav-item nav-link" data-toggle="try">Try CoffeeScript</a>
<a href="#language" class="nav-item nav-link" data-close="try">Language Reference</a>
<a href="#integrations" class="nav-item nav-link" data-close="try">Integrations</a>
<a href="#resources" class="nav-item nav-link" data-close="try">Resources</a>
<a href="https://github.com/jashkenas/coffeescript/" class="nav-item nav-link" data-close="try">GitHub
</a>

View File

@@ -1,9 +1,14 @@
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/combine/npm/codemirror@5.37.0/lib/codemirror.js,npm/codemirror@5.37.0/mode/coffeescript/coffeescript.js,npm/codemirror@5.37.0/addon/lint/coffeescript-lint.js,npm/codemirror@5.37.0/mode/javascript/javascript.js"></script>
<script src="browser-compiler/coffeescript.js"></script>
<script>
<script nomodule src="./browser-compiler-legacy/coffeescript.js"></script>
<script nomodule>
<%= includeScript('docs.coffee') %>
</script>
<script type="module">
import CoffeeScript from './browser-compiler-modern/coffeescript.js';
<%= includeScript('docs.coffee') %>
</script>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-106156830-1"></script>

View File

@@ -36,7 +36,8 @@
<a href="#async-functions" class="nav-link" data-action="sidebar-nav">Async Functions</a>
<a href="#classes" class="nav-link" data-action="sidebar-nav">Classes</a>
<a href="#prototypal-inheritance" class="nav-link" data-action="sidebar-nav">Prototypal Inheritance</a>
<a href="#switch" class="nav-link" data-action="sidebar-nav">Switch and Try/Catch</a>
<a href="#switch" class="nav-link" data-action="sidebar-nav">Switch/When/Else</a>
<a href="#try-catch" class="nav-link" data-action="sidebar-nav">Try/Catch/Finally</a>
<a href="#comparisons" class="nav-link" data-action="sidebar-nav">Chained Comparisons</a>
<a href="#regexes" class="nav-link" data-action="sidebar-nav">Block Regular Expressions</a>
<a href="#tagged-template-literals" class="nav-link" data-action="sidebar-nav">Tagged Template Literals</a>
@@ -49,7 +50,14 @@
<a href="#source-maps" class="nav-link" data-action="sidebar-nav">Source Maps</a>
<a href="#cake" class="nav-link" data-action="sidebar-nav">Cake, and Cakefiles</a>
<a href="#scripts" class="nav-link" data-action="sidebar-nav"><code>"text/coffeescript"</code> Script Tags</a>
<a href="test.html" class="nav-link" data-action="sidebar-nav">Browser-Based Tests</a>
<a href="#integrations" class="nav-link" data-action="sidebar-nav">Integrations</a>
<nav class="nav flex-column">
<a href="#build-tools" class="nav-link" data-action="sidebar-nav">Build Tools</a>
<a href="#code-editors" class="nav-link" data-action="sidebar-nav">Code Editors</a>
<a href="#frameworks" class="nav-link" data-action="sidebar-nav">Frameworks</a>
<a href="#linters-and-formatting" class="nav-link" data-action="sidebar-nav">Linters and Formatting</a>
<a href="#testing" class="nav-link" data-action="sidebar-nav">Testing</a>
</nav>
<a href="#resources" class="nav-link" data-action="sidebar-nav">Resources</a>
<nav class="nav flex-column">
<a href="#books" class="nav-link" data-action="sidebar-nav">Books</a>
@@ -79,6 +87,7 @@
<a href="#breaking-changes-argument-parsing-and-shebang-lines" class="nav-link" data-action="sidebar-nav">Argument Parsing and <code>#!</code> Lines</a>
</nav>
<a href="#changelog" class="nav-link" data-action="sidebar-nav">Changelog</a>
<a href="test.html" class="nav-link" data-action="sidebar-nav">Browser-Based Tests</a>
<a href="/v1/" class="nav-link" data-action="sidebar-nav">Version 1.x Documentation</a>
</nav>
</nav>

View File

@@ -1,7 +1,7 @@
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<!-- The CoffeeScript logo font is Googles Galada -->
<link href="https://fonts.googleapis.com/css?family=Alegreya+Sans:400,800|Lato:300,300i,400,700|Roboto+Mono:400,400i" rel="stylesheet" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/npm/codemirror@5.37.0/lib/codemirror.css" rel="stylesheet" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/npm/codemirror@5.62.3/lib/codemirror.css" rel="stylesheet" crossorigin="anonymous">
<style>
<%= include('code.css') %>
<%= include('docs.css') %>

View File

@@ -3,7 +3,12 @@
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>CoffeeScript Test Suite</title>
<script src="browser-compiler/coffeescript.js"></script>
<script nomodule src="browser-compiler-legacy/coffeescript.js"></script>
<script type="module">
import CoffeeScript from './browser-compiler-modern/coffeescript.js';
window.CoffeeScript = CoffeeScript;
window.addEventListener('DOMContentLoaded', CoffeeScript.runScripts, false);
</script>
<script src="https://cdn.jsdelivr.net/underscorejs/1.8.3/underscore-min.js"></script>
<style>
body, pre {
@@ -39,15 +44,16 @@
<script type="text/coffeescript">
@testingBrowser = yes
@global = window
bold = red = green = reset = ''
@bold = @red = @green = @reset = ''
stdout = document.getElementById 'stdout'
start = new Date
@currentFile = ''
@passedTests = failedTests = total = done = 0
say = (msg, className) ->
say = (msg, className, id) ->
div = document.createElement 'div'
div.className = className if className?
div.id = id if id?
div.appendChild document.createTextNode msg
stdout.appendChild div
msg
@@ -132,7 +138,7 @@ done = ->
sec = (new Date - start) / 1000
msg = "passed #{passedTests} tests in #{sec.toFixed 2} seconds"
msg = "failed #{total - passedTests} tests and #{msg}" unless yay
say msg, (if yay then 'good' else 'bad')
say msg, (if yay then 'good' else 'bad'), 'result'
gtag 'event', 'tests_complete',
event_category: 'tests'

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,10 +1,10 @@
// Generated by CoffeeScript 2.3.2
// Generated by CoffeeScript 2.7.0
(function() {
// This **Browser** compatibility layer extends core CoffeeScript functions
// to make things work smoothly when compiling code directly in the browser.
// We add support for loading remote Coffee scripts via **XHR**, and
// `text/coffeescript` script tags, source maps via data-URLs, and so on.
var CoffeeScript, compile, runScripts,
var CoffeeScript, compile,
indexOf = [].indexOf;
CoffeeScript = require('./coffeescript');
@@ -81,7 +81,7 @@
// Activate CoffeeScript in the browser by having it compile and evaluate
// all script tags with a content-type of `text/coffeescript`.
// This happens on page load.
runScripts = function() {
CoffeeScript.runScripts = function() {
var coffees, coffeetypes, execute, i, index, j, len, s, script, scripts;
scripts = window.document.getElementsByTagName('script');
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript'];
@@ -126,7 +126,7 @@
// filename; otherwise use `coffeescript`, or `coffeescript1` etc.,
// leaving the first one unnumbered for the common case that theres
// only one CoffeeScript script block to parse.
options.filename = script.id && script.id !== '' ? script.id : `coffeescript${(i !== 0 ? i : '')}`;
options.filename = script.id && script.id !== '' ? script.id : `coffeescript${i !== 0 ? i : ''}`;
options.sourceFiles = ['embedded'];
return coffees[i] = [script.innerHTML, options];
}
@@ -136,10 +136,16 @@
};
// Listen for window load, both in decent browsers and in IE.
if (window.addEventListener) {
window.addEventListener('DOMContentLoaded', runScripts, false);
} else {
window.attachEvent('onload', runScripts);
// Only attach this event handler on startup for the
// non-ES module version of the browser compiler, to preserve
// backward compatibility while letting the ES module version
// be importable without side effects.
if (this === window) {
if (window.addEventListener) {
window.addEventListener('DOMContentLoaded', CoffeeScript.runScripts, false);
} else {
window.attachEvent('onload', CoffeeScript.runScripts);
}
}
}).call(this);

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.3.2
// Generated by CoffeeScript 2.7.0
(function() {
// `cake` is a simplified version of [Make](http://www.gnu.org/software/make/)
// ([Rake](http://rake.rubyforge.org/), [Jake](https://github.com/280north/jake))

View File

@@ -1,11 +1,10 @@
// Generated by CoffeeScript 2.3.2
// Generated by CoffeeScript 2.7.0
(function() {
// CoffeeScript can be used both on the server, as a command-line compiler based
// on Node.js/V8, or to run CoffeeScript directly in the browser. This module
// contains the main entry functions for tokenizing, parsing, and compiling
// source CoffeeScript into JavaScript.
var FILE_EXTENSIONS, Lexer, SourceMap, base64encode, checkShebangLine, compile, formatSourcePosition, getSourceMap, helpers, lexer, packageJson, parser, sourceMaps, sources, withPrettyErrors,
indexOf = [].indexOf;
var FILE_EXTENSIONS, Lexer, SourceMap, base64encode, checkShebangLine, compile, getSourceMap, helpers, lexer, packageJson, parser, registerCompiled, withPrettyErrors;
({Lexer} = require('./lexer'));
@@ -27,6 +26,13 @@
// Expose helpers for testing.
exports.helpers = helpers;
({getSourceMap, registerCompiled} = SourceMap);
// This is exported to enable an external module to implement caching of
// sourcemaps. This is used only when `patchStackTrace` has been called to adjust
// stack traces for files with cached source maps.
exports.registerCompiled = registerCompiled;
// Function that allows for btoa in both nodejs and the browser.
base64encode = function(src) {
switch (false) {
@@ -62,18 +68,6 @@
};
};
// For each compiled file, save its source in memory in case we need to
// recompile it later. We might need to recompile if the first compilation
// didnt create a source map (faster) but something went wrong and we need
// a stack trace. Assuming that most of the time, code isnt throwing
// exceptions, its probably more efficient to compile twice only when we
// need a stack trace, rather than always generating a source map even when
// its not likely to be used. Save in form of `filename`: [`(source)`]
sources = {};
// Also save source maps if generated, in form of `(source)`: [`(source map)`].
sourceMaps = {};
// Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
// If `options.sourceMap` is specified, then `options.filename` must also be
@@ -85,21 +79,14 @@
// object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for
// doing programmatic lookups.
exports.compile = compile = withPrettyErrors(function(code, options = {}) {
var currentColumn, currentLine, encoded, filename, fragment, fragments, generateSourceMap, header, i, j, js, len, len1, map, newLines, ref, ref1, sourceMapDataURI, sourceURL, token, tokens, transpiler, transpilerOptions, transpilerOutput, v3SourceMap;
var ast, currentColumn, currentLine, encoded, filename, fragment, fragments, generateSourceMap, header, i, j, js, len, len1, map, newLines, nodes, range, ref, sourceCodeLastLine, sourceCodeNumberOfLines, sourceMapDataURI, sourceURL, token, tokens, transpiler, transpilerOptions, transpilerOutput, v3SourceMap;
// Clone `options`, to avoid mutating the `options` object passed in.
options = Object.assign({}, options);
// Always generate a source map if no filename is passed in, since without a
// a filename we have no way to retrieve this source later in the event that
// we need to recompile it to get a source map for `prepareStackTrace`.
generateSourceMap = options.sourceMap || options.inlineMap || (options.filename == null);
filename = options.filename || '<anonymous>';
filename = options.filename || helpers.anonymousFileName();
checkShebangLine(filename, code);
if (sources[filename] == null) {
sources[filename] = [];
}
sources[filename].push(code);
if (generateSourceMap) {
map = new SourceMap;
map = new SourceMap();
}
tokens = lexer.tokenize(code, options);
// Pass a list of referenced variables, so that generated variables wont get
@@ -125,7 +112,31 @@
}
}
}
fragments = parser.parse(tokens).compileToFragments(options);
nodes = parser.parse(tokens);
// If all that was requested was a POJO representation of the nodes, e.g.
// the abstract syntax tree (AST), we can stop now and just return that
// (after fixing the location data for the root/`File`»`Program` node,
// which mightve gotten misaligned from the original source due to the
// `clean` function in the lexer).
if (options.ast) {
nodes.allCommentTokens = helpers.extractAllCommentTokens(tokens);
sourceCodeNumberOfLines = (code.match(/\r?\n/g) || '').length + 1;
sourceCodeLastLine = /.*$/.exec(code)[0];
ast = nodes.ast(options);
range = [0, code.length];
ast.start = ast.program.start = range[0];
ast.end = ast.program.end = range[1];
ast.range = ast.program.range = range;
ast.loc.start = ast.program.loc.start = {
line: 1,
column: 0
};
ast.loc.end.line = ast.program.loc.end.line = sourceCodeNumberOfLines;
ast.loc.end.column = ast.program.loc.end.column = sourceCodeLastLine.length;
ast.tokens = tokens;
return ast;
}
fragments = nodes.compileToFragments(options);
currentLine = 0;
if (options.header) {
currentLine += 1;
@@ -162,10 +173,6 @@
}
if (generateSourceMap) {
v3SourceMap = map.generate(options, code);
if (sourceMaps[filename] == null) {
sourceMaps[filename] = [];
}
sourceMaps[filename].push(map);
}
if (options.transpile) {
if (typeof options.transpile !== 'object') {
@@ -193,9 +200,10 @@
if (options.inlineMap) {
encoded = base64encode(JSON.stringify(v3SourceMap));
sourceMapDataURI = `//# sourceMappingURL=data:application/json;base64,${encoded}`;
sourceURL = `//# sourceURL=${(ref1 = options.filename) != null ? ref1 : 'coffeescript'}`;
sourceURL = `//# sourceURL=${filename}`;
js = `${js}\n${sourceMapDataURI}\n${sourceURL}`;
}
registerCompiled(filename, code, map);
if (options.sourceMap) {
return {
js,
@@ -217,10 +225,9 @@
// or traverse it by using `.traverseChildren()` with a callback.
exports.nodes = withPrettyErrors(function(source, options) {
if (typeof source === 'string') {
return parser.parse(lexer.tokenize(source, options));
} else {
return parser.parse(source);
source = lexer.tokenize(source, options);
}
return parser.parse(source);
});
// This file used to export these methods; leave stubs that throw warnings
@@ -233,12 +240,18 @@
};
// Instantiate a Lexer for our use here.
lexer = new Lexer;
lexer = new Lexer();
// The real Lexer produces a generic stream of tokens. This object provides a
// thin wrapper around it, compatible with the Jison API. We can then pass it
// directly as a “Jison lexer.”
parser.lexer = {
yylloc: {
range: []
},
options: {
ranges: true
},
lex: function() {
var tag, token;
token = parser.tokens[this.pos++];
@@ -290,110 +303,58 @@
return helpers.throwSyntaxError(`unexpected ${errorText}`, errorLoc);
};
// Based on http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js
// Modified to handle sourceMap
formatSourcePosition = function(frame, getSourceMapping) {
var as, column, fileLocation, filename, functionName, isConstructor, isMethodCall, line, methodName, source, tp, typeName;
filename = void 0;
fileLocation = '';
if (frame.isNative()) {
fileLocation = "native";
} else {
if (frame.isEval()) {
filename = frame.getScriptNameOrSourceURL();
if (!filename) {
fileLocation = `${frame.getEvalOrigin()}, `;
}
exports.patchStackTrace = function() {
var formatSourcePosition, getSourceMapping;
// Based on http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js
// Modified to handle sourceMap
formatSourcePosition = function(frame, getSourceMapping) {
var as, column, fileLocation, filename, functionName, isConstructor, isMethodCall, line, methodName, source, tp, typeName;
filename = void 0;
fileLocation = '';
if (frame.isNative()) {
fileLocation = "native";
} else {
filename = frame.getFileName();
if (frame.isEval()) {
filename = frame.getScriptNameOrSourceURL();
if (!filename) {
fileLocation = `${frame.getEvalOrigin()}, `;
}
} else {
filename = frame.getFileName();
}
filename || (filename = "<anonymous>");
line = frame.getLineNumber();
column = frame.getColumnNumber();
// Check for a sourceMap position
source = getSourceMapping(filename, line, column);
fileLocation = source ? `${filename}:${source[0]}:${source[1]}` : `${filename}:${line}:${column}`;
}
filename || (filename = "<anonymous>");
line = frame.getLineNumber();
column = frame.getColumnNumber();
// Check for a sourceMap position
source = getSourceMapping(filename, line, column);
fileLocation = source ? `${filename}:${source[0]}:${source[1]}` : `${filename}:${line}:${column}`;
}
functionName = frame.getFunctionName();
isConstructor = frame.isConstructor();
isMethodCall = !(frame.isToplevel() || isConstructor);
if (isMethodCall) {
methodName = frame.getMethodName();
typeName = frame.getTypeName();
if (functionName) {
tp = as = '';
if (typeName && functionName.indexOf(typeName)) {
tp = `${typeName}.`;
functionName = frame.getFunctionName();
isConstructor = frame.isConstructor();
isMethodCall = !(frame.isToplevel() || isConstructor);
if (isMethodCall) {
methodName = frame.getMethodName();
typeName = frame.getTypeName();
if (functionName) {
tp = as = '';
if (typeName && functionName.indexOf(typeName)) {
tp = `${typeName}.`;
}
if (methodName && functionName.indexOf(`.${methodName}`) !== functionName.length - methodName.length - 1) {
as = ` [as ${methodName}]`;
}
return `${tp}${functionName}${as} (${fileLocation})`;
} else {
return `${typeName}.${methodName || '<anonymous>'} (${fileLocation})`;
}
if (methodName && functionName.indexOf(`.${methodName}`) !== functionName.length - methodName.length - 1) {
as = ` [as ${methodName}]`;
}
return `${tp}${functionName}${as} (${fileLocation})`;
} else if (isConstructor) {
return `new ${functionName || '<anonymous>'} (${fileLocation})`;
} else if (functionName) {
return `${functionName} (${fileLocation})`;
} else {
return `${typeName}.${methodName || '<anonymous>'} (${fileLocation})`;
return fileLocation;
}
} else if (isConstructor) {
return `new ${functionName || '<anonymous>'} (${fileLocation})`;
} else if (functionName) {
return `${functionName} (${fileLocation})`;
} else {
return fileLocation;
}
};
getSourceMap = function(filename, line, column) {
var answer, i, map, ref, ref1, sourceLocation;
if (!(filename === '<anonymous>' || (ref = filename.slice(filename.lastIndexOf('.')), indexOf.call(FILE_EXTENSIONS, ref) >= 0))) {
// Skip files that we didnt compile, like Node system files that appear in
// the stack trace, as they never have source maps.
return null;
}
if (filename !== '<anonymous>' && (sourceMaps[filename] != null)) {
return sourceMaps[filename][sourceMaps[filename].length - 1];
// CoffeeScript compiled in a browser or via `CoffeeScript.compile` or `.run`
// may get compiled with `options.filename` thats missing, which becomes
// `<anonymous>`; but the runtime might request the stack trace with the
// filename of the script file. See if we have a source map cached under
// `<anonymous>` that matches the error.
} else if (sourceMaps['<anonymous>'] != null) {
ref1 = sourceMaps['<anonymous>'];
// Work backwards from the most recent anonymous source maps, until we find
// one that works. This isnt foolproof; there is a chance that multiple
// source maps will have line/column pairs that match. But we have no other
// way to match them. `frame.getFunction().toString()` doesnt always work,
// and its not foolproof either.
for (i = ref1.length - 1; i >= 0; i += -1) {
map = ref1[i];
sourceLocation = map.sourceLocation([line - 1, column - 1]);
if (((sourceLocation != null ? sourceLocation[0] : void 0) != null) && (sourceLocation[1] != null)) {
return map;
}
}
}
// If all else fails, recompile this source to get a source map. We need the
// previous section (for `<anonymous>`) despite this option, because after it
// gets compiled we will still need to look it up from
// `sourceMaps['<anonymous>']` in order to find and return it. Thats why we
// start searching from the end in the previous block, because most of the
// time the source map we want is the last one.
if (sources[filename] != null) {
answer = compile(sources[filename][sources[filename].length - 1], {
filename: filename,
sourceMap: true,
literate: helpers.isLiterate(filename)
});
return answer.sourceMap;
} else {
return null;
}
};
// Based on [michaelficarra/CoffeeScriptRedux](http://goo.gl/ZTx1p)
// NodeJS / V8 have no support for transforming positions in stack traces using
// sourceMap, so we must monkey-patch Error to display CoffeeScript source
// positions.
Error.prepareStackTrace = function(err, stack) {
var frame, frames, getSourceMapping;
};
getSourceMapping = function(filename, line, column) {
var answer, sourceMap;
sourceMap = getSourceMap(filename, line, column);
@@ -406,19 +367,27 @@
return null;
}
};
frames = (function() {
var i, len, results;
results = [];
for (i = 0, len = stack.length; i < len; i++) {
frame = stack[i];
if (frame.getFunction() === exports.run) {
break;
// Based on [michaelficarra/CoffeeScriptRedux](http://goo.gl/ZTx1p)
// NodeJS / V8 have no support for transforming positions in stack traces using
// sourceMap, so we must monkey-patch Error to display CoffeeScript source
// positions.
return Error.prepareStackTrace = function(err, stack) {
var frame, frames;
frames = (function() {
var i, len, results;
results = [];
for (i = 0, len = stack.length; i < len; i++) {
frame = stack[i];
if (frame.getFunction() === exports.run) {
// Dont display stack frames deeper than `CoffeeScript.run`.
break;
}
results.push(` at ${formatSourcePosition(frame, getSourceMapping)}`);
}
results.push(` at ${formatSourcePosition(frame, getSourceMapping)}`);
}
return results;
})();
return `${err.toString()}\n${frames.join('\n')}\n`;
return results;
})();
return `${err.toString()}\n${frames.join('\n')}\n`;
};
};
checkShebangLine = function(file, input) {
@@ -429,7 +398,9 @@
return s !== '';
}) : void 0 : void 0;
if ((args != null ? args.length : void 0) > 1) {
console.error('The script to be run begins with a shebang line with more than one\nargument. This script will fail on platforms such as Linux which only\nallow a single argument.');
console.error(`The script to be run begins with a shebang line with more than one
argument. This script will fail on platforms such as Linux which only
allow a single argument.`);
console.error(`The shebang line was: '${firstLine}' in file '${file}'`);
return console.error(`The arguments were: ${JSON.stringify(args)}`);
}

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.3.2
// Generated by CoffeeScript 2.7.0
(function() {
// The `coffee` utility. Handles command-line compilation of CoffeeScript
// into various forms: saved into `.js` files or printed to stdout
@@ -27,7 +27,7 @@
useWinPathSep = path.sep === '\\';
// Allow CoffeeScript to emit Node.js events.
helpers.extend(CoffeeScript, new EventEmitter);
helpers.extend(CoffeeScript, new EventEmitter());
printLine = function(line) {
return process.stdout.write(line + '\n');
@@ -42,10 +42,12 @@
};
// The help banner that is printed in conjunction with `-h`/`--help`.
BANNER = 'Usage: coffee [options] path/to/script.coffee [args]\n\nIf called without options, `coffee` will run your script.';
BANNER = `Usage: coffee [options] path/to/script.coffee [args]
If called without options, \`coffee\` will run your script.`;
// The list of all the valid option flags that `coffee` knows how to handle.
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-m', '--map', 'generate source map and save as .js.map files'], ['-M', '--inline-map', 'generate source map and include it directly in output'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['--no-header', 'suppress the "Generated by" header'], ['-o', '--output [PATH]', 'set the output path or path/filename for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [MODULE*]', 'require the given module before eval or REPL'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-l', '--literate', 'treat stdio as literate style coffeescript'], ['-t', '--transpile', 'pipe generated JavaScript through Babel'], ['--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
SWITCHES = [['--ast', 'generate an abstract syntax tree of nodes'], ['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-l', '--literate', 'treat stdio as literate style coffeescript'], ['-m', '--map', 'generate source map and save as .js.map files'], ['-M', '--inline-map', 'generate source map and include it directly in output'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['--no-header', 'suppress the "Generated by" header'], ['-o', '--output [PATH]', 'set the output path or path/filename for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [MODULE*]', 'require the given module before eval or REPL'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-t', '--transpile', 'pipe generated JavaScript through Babel'], ['--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
// Top-level objects shared by all the functions.
opts = {};
@@ -78,7 +80,11 @@
process.exit(1);
}
if ((!opts.doubleDashed) && (opts.arguments[1] === '--')) {
printWarn('coffee was invoked with \'--\' as the second positional argument, which is\nnow deprecated. To pass \'--\' as an argument to a script to run, put an\nadditional \'--\' before the path to your script.\n\n\'--\' will be removed from the argument list.');
printWarn(`coffee was invoked with '--' as the second positional argument, which is
now deprecated. To pass '--' as an argument to a script to run, put an
additional '--' before the path to your script.
'--' will be removed from the argument list.`);
printWarn(`The positional arguments were: ${JSON.stringify(opts.arguments)}`);
opts.arguments = [opts.arguments[0]].concat(opts.arguments.slice(2));
}
@@ -131,7 +137,18 @@
}
if (opts.join) {
opts.join = path.resolve(opts.join);
console.error('\nThe --join option is deprecated and will be removed in a future version.\n\nIf for some reason it\'s necessary to share local variables between files,\nreplace...\n\n $ coffee --compile --join bundle.js -- a.coffee b.coffee c.coffee\n\nwith...\n\n $ cat a.coffee b.coffee c.coffee | coffee --compile --stdio > bundle.js\n');
console.error(`
The --join option is deprecated and will be removed in a future version.
If for some reason it's necessary to share local variables between files,
replace...
$ coffee --compile --join bundle.js -- a.coffee b.coffee c.coffee
with...
$ cat a.coffee b.coffee c.coffee | coffee --compile --stdio > bundle.js
`);
}
ref = opts.arguments;
results = [];
@@ -257,6 +274,9 @@
return printTokens(CoffeeScript.tokens(task.input, task.options));
} else if (opts.nodes) {
return printLine(CoffeeScript.nodes(task.input, task.options).toString().trim());
} else if (opts.ast) {
compiled = CoffeeScript.compile(task.input, task.options);
return printLine(JSON.stringify(compiled, null, 2));
} else if (opts.run) {
CoffeeScript.register();
if (opts.prelude) {
@@ -578,7 +598,7 @@
// When watching scripts, it's useful to log changes with the timestamp.
timeLog = function(message) {
return console.log(`${(new Date).toLocaleTimeString()} - ${message}`);
return console.log(`${(new Date()).toLocaleTimeString()} - ${message}`);
};
// Pretty-print a stream of tokens, sans location data.
@@ -627,9 +647,15 @@
// Give appropriate instructions depending on whether `coffee` was run
// locally or globally.
if (require.resolve('.').indexOf(process.cwd()) === 0) {
console.error('To use --transpile, you must have @babel/core installed:\n npm install --save-dev @babel/core\nAnd you must save options to configure Babel in one of the places it looks to find its options.\nSee https://coffeescript.org/#transpilation');
console.error(`To use --transpile, you must have @babel/core installed:
npm install --save-dev @babel/core
And you must save options to configure Babel in one of the places it looks to find its options.
See https://coffeescript.org/#transpilation`);
} else {
console.error('To use --transpile with globally-installed CoffeeScript, you must have @babel/core installed globally:\n npm install --global @babel/core\nAnd you must save options to configure Babel in one of the places it looks to find its options, relative to the file being compiled or to the current folder.\nSee https://coffeescript.org/#transpilation');
console.error(`To use --transpile with globally-installed CoffeeScript, you must have @babel/core installed globally:
npm install --global @babel/core
And you must save options to configure Babel in one of the places it looks to find its options, relative to the file being compiled or to the current folder.
See https://coffeescript.org/#transpilation`);
}
process.exit(1);
}
@@ -659,7 +685,8 @@
header: opts.compile && !opts['no-header'],
transpile: opts.transpile,
sourceMap: opts.map,
inlineMap: opts['inline-map']
inlineMap: opts['inline-map'],
ast: opts.ast
};
if (filename) {
if (base) {
@@ -668,7 +695,7 @@
jsDir = path.dirname(jsPath);
answer = helpers.merge(answer, {
jsPath,
sourceRoot: path.relative(jsDir, cwd),
sourceRoot: path.relative(jsDir, cwd) + path.sep,
sourceFiles: [path.relative(cwd, filename)],
generatedFile: helpers.baseFileName(jsPath, false, useWinPathSep)
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,12 @@
// Generated by CoffeeScript 2.3.2
// Generated by CoffeeScript 2.7.0
(function() {
// This file contains the common helper functions that we'd like to share among
// the **Lexer**, **Rewriter**, and the **Nodes**. Merge objects, flatten
// arrays, count characters, that sort of thing.
// Peek at the beginning of a given string to see if it matches a sequence.
var attachCommentsToNode, buildLocationData, buildLocationHash, buildTokenDataDictionary, extend, flatten, ref, repeat, syntaxErrorToString;
var UNICODE_CODE_POINT_ESCAPE, attachCommentsToNode, buildLocationData, buildLocationHash, buildTokenDataDictionary, extend, flatten, isBoolean, isNumber, isString, ref, repeat, syntaxErrorToString, unicodeCodePointToUnicodeEscapes,
indexOf = [].indexOf;
exports.starts = function(string, literal, start) {
return literal === string.substr(start, literal.length);
@@ -156,23 +157,55 @@
first_line: first.first_line,
first_column: first.first_column,
last_line: last.last_line,
last_column: last.last_column
last_column: last.last_column,
last_line_exclusive: last.last_line_exclusive,
last_column_exclusive: last.last_column_exclusive,
range: [first.range[0], last.range[1]]
};
}
};
// Build a list of all comments attached to tokens.
exports.extractAllCommentTokens = function(tokens) {
var allCommentsObj, comment, commentKey, i, j, k, key, len1, len2, len3, ref1, results, sortedKeys, token;
allCommentsObj = {};
for (i = 0, len1 = tokens.length; i < len1; i++) {
token = tokens[i];
if (token.comments) {
ref1 = token.comments;
for (j = 0, len2 = ref1.length; j < len2; j++) {
comment = ref1[j];
commentKey = comment.locationData.range[0];
allCommentsObj[commentKey] = comment;
}
}
}
sortedKeys = Object.keys(allCommentsObj).sort(function(a, b) {
return a - b;
});
results = [];
for (k = 0, len3 = sortedKeys.length; k < len3; k++) {
key = sortedKeys[k];
results.push(allCommentsObj[key]);
}
return results;
};
// Get a lookup hash for a token based on its location data.
// Multiple tokens might have the same location hash, but using exclusive
// location data distinguishes e.g. zero-length generated tokens from
// actual source tokens.
buildLocationHash = function(loc) {
return `${loc.first_line}x${loc.first_column}-${loc.last_line}x${loc.last_column}`;
return `${loc.range[0]}-${loc.range[1]}`;
};
// Build a dictionary of extra token properties organized by tokens locations
// used as lookup hashes.
buildTokenDataDictionary = function(parserState) {
var base, i, len1, ref1, token, tokenData, tokenHash;
exports.buildTokenDataDictionary = buildTokenDataDictionary = function(tokens) {
var base1, i, len1, token, tokenData, tokenHash;
tokenData = {};
ref1 = parserState.parser.tokens;
for (i = 0, len1 = ref1.length; i < len1; i++) {
token = ref1[i];
for (i = 0, len1 = tokens.length; i < len1; i++) {
token = tokens[i];
if (!token.comments) {
continue;
}
@@ -188,7 +221,7 @@
// and therefore matching `tokenHash`es, merge the comments from both/all
// tokens together into one array, even if there are duplicate comments;
// they will get sorted out later.
((base = tokenData[tokenHash]).comments != null ? base.comments : base.comments = []).push(...token.comments);
((base1 = tokenData[tokenHash]).comments != null ? base1.comments : base1.comments = []).push(...token.comments);
}
}
return tokenData;
@@ -197,21 +230,24 @@
// This returns a function which takes an object as a parameter, and if that
// object is an AST node, updates that object's locationData.
// The object is returned either way.
exports.addDataToNode = function(parserState, first, last) {
exports.addDataToNode = function(parserState, firstLocationData, firstValue, lastLocationData, lastValue, forceUpdateLocation = true) {
return function(obj) {
var objHash, ref1;
var locationData, objHash, ref1, ref2, ref3;
// Add location data.
if (((obj != null ? obj.updateLocationDataIfMissing : void 0) != null) && (first != null)) {
obj.updateLocationDataIfMissing(buildLocationData(first, last));
locationData = buildLocationData((ref1 = firstValue != null ? firstValue.locationData : void 0) != null ? ref1 : firstLocationData, (ref2 = lastValue != null ? lastValue.locationData : void 0) != null ? ref2 : lastLocationData);
if (((obj != null ? obj.updateLocationDataIfMissing : void 0) != null) && (firstLocationData != null)) {
obj.updateLocationDataIfMissing(locationData, forceUpdateLocation);
} else {
obj.locationData = locationData;
}
// Add comments, building the dictionary of token data if it hasnt been
// built yet.
if (parserState.tokenData == null) {
parserState.tokenData = buildTokenDataDictionary(parserState);
parserState.tokenData = buildTokenDataDictionary(parserState.parser.tokens);
}
if (obj.locationData != null) {
objHash = buildLocationHash(obj.locationData);
if (((ref1 = parserState.tokenData[objHash]) != null ? ref1.comments : void 0) != null) {
if (((ref3 = parserState.tokenData[objHash]) != null ? ref3.comments : void 0) != null) {
attachCommentsToNode(parserState.tokenData[objHash].comments, obj);
}
}
@@ -245,6 +281,16 @@
}
};
// Generate a unique anonymous file name so we can distinguish source map cache
// entries for any number of anonymous scripts.
exports.anonymousFileName = (function() {
var n;
n = 0;
return function() {
return `<anonymous-${n++}>`;
};
})();
// A `.coffee.md` compatible version of `basename`, that returns the file sans-extension.
exports.baseFileName = function(file, stripExt = false, useWinPathSep = false) {
var parts, pathSep;
@@ -301,7 +347,7 @@
};
syntaxErrorToString = function() {
var codeLine, colorize, colorsEnabled, end, filename, first_column, first_line, last_column, last_line, marker, ref1, ref2, ref3, start;
var codeLine, colorize, colorsEnabled, end, filename, first_column, first_line, last_column, last_line, marker, ref1, ref2, ref3, ref4, start;
if (!(this.code && this.location)) {
return Error.prototype.toString.call(this);
}
@@ -312,7 +358,11 @@
if (last_column == null) {
last_column = first_column;
}
filename = this.filename || '[stdin]';
if ((ref1 = this.filename) != null ? ref1.startsWith('<anonymous') : void 0) {
filename = '[stdin]';
} else {
filename = this.filename || '[stdin]';
}
codeLine = this.code.split('\n')[first_line];
start = first_column;
// Show only the first line on multi-line errors.
@@ -320,16 +370,18 @@
marker = codeLine.slice(0, start).replace(/[^\s]/g, ' ') + repeat('^', end - start);
// Check to see if we're running on a color-enabled TTY.
if (typeof process !== "undefined" && process !== null) {
colorsEnabled = ((ref1 = process.stdout) != null ? ref1.isTTY : void 0) && !((ref2 = process.env) != null ? ref2.NODE_DISABLE_COLORS : void 0);
colorsEnabled = ((ref2 = process.stdout) != null ? ref2.isTTY : void 0) && !((ref3 = process.env) != null ? ref3.NODE_DISABLE_COLORS : void 0);
}
if ((ref3 = this.colorful) != null ? ref3 : colorsEnabled) {
if ((ref4 = this.colorful) != null ? ref4 : colorsEnabled) {
colorize = function(str) {
return `\x1B[1;31m${str}\x1B[0m`;
};
codeLine = codeLine.slice(0, start) + colorize(codeLine.slice(start, end)) + codeLine.slice(end);
marker = colorize(marker);
}
return `${filename}:${first_line + 1}:${first_column + 1}: error: ${this.message}\n${codeLine}\n${marker}`;
return `${filename}:${first_line + 1}:${first_column + 1}: error: ${this.message}
${codeLine}
${marker}`;
};
exports.nameWhitespaceCharacter = function(string) {
@@ -347,4 +399,89 @@
}
};
exports.parseNumber = function(string) {
var base;
if (string == null) {
return 0/0;
}
base = (function() {
switch (string.charAt(1)) {
case 'b':
return 2;
case 'o':
return 8;
case 'x':
return 16;
default:
return null;
}
})();
if (base != null) {
return parseInt(string.slice(2).replace(/_/g, ''), base);
} else {
return parseFloat(string.replace(/_/g, ''));
}
};
exports.isFunction = function(obj) {
return Object.prototype.toString.call(obj) === '[object Function]';
};
exports.isNumber = isNumber = function(obj) {
return Object.prototype.toString.call(obj) === '[object Number]';
};
exports.isString = isString = function(obj) {
return Object.prototype.toString.call(obj) === '[object String]';
};
exports.isBoolean = isBoolean = function(obj) {
return obj === true || obj === false || Object.prototype.toString.call(obj) === '[object Boolean]';
};
exports.isPlainObject = function(obj) {
return typeof obj === 'object' && !!obj && !Array.isArray(obj) && !isNumber(obj) && !isString(obj) && !isBoolean(obj);
};
unicodeCodePointToUnicodeEscapes = function(codePoint) {
var high, low, toUnicodeEscape;
toUnicodeEscape = function(val) {
var str;
str = val.toString(16);
return `\\u${repeat('0', 4 - str.length)}${str}`;
};
if (codePoint < 0x10000) {
return toUnicodeEscape(codePoint);
}
// surrogate pair
high = Math.floor((codePoint - 0x10000) / 0x400) + 0xD800;
low = (codePoint - 0x10000) % 0x400 + 0xDC00;
return `${toUnicodeEscape(high)}${toUnicodeEscape(low)}`;
};
// Replace `\u{...}` with `\uxxxx[\uxxxx]` in regexes without `u` flag
exports.replaceUnicodeCodePointEscapes = function(str, {flags, error, delimiter = ''} = {}) {
var shouldReplace;
shouldReplace = (flags != null) && indexOf.call(flags, 'u') < 0;
return str.replace(UNICODE_CODE_POINT_ESCAPE, function(match, escapedBackslash, codePointHex, offset) {
var codePointDecimal;
if (escapedBackslash) {
return escapedBackslash;
}
codePointDecimal = parseInt(codePointHex, 16);
if (codePointDecimal > 0x10ffff) {
error("unicode code point escapes greater than \\u{10ffff} are not allowed", {
offset: offset + delimiter.length,
length: codePointHex.length + 4
});
}
if (!shouldReplace) {
return match;
}
return unicodeCodePointToUnicodeEscapes(codePointDecimal);
});
};
UNICODE_CODE_POINT_ESCAPE = /(\\\\)|\\u\{([\da-fA-F]+)\}/g; // Make sure the escape isnt escaped.
}).call(this);

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.3.2
// Generated by CoffeeScript 2.7.0
(function() {
// Node.js Implementation
var CoffeeScript, ext, fs, helpers, i, len, path, ref, universalCompile, vm,
@@ -51,7 +51,7 @@
var answer, dir, mainModule, ref;
mainModule = require.main;
// Set the filename.
mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '<anonymous>';
mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : helpers.anonymousFileName();
// Clear the module cache.
mainModule.moduleCache && (mainModule.moduleCache = {});
// Assign paths for node_modules loading
@@ -59,11 +59,11 @@
mainModule.paths = require('module')._nodeModulePaths(dir);
// Save the options for compiling child imports.
mainModule.options = options;
options.filename = mainModule.filename;
options.inlineMap = true;
// Compile.
if (!helpers.isCoffee(mainModule.filename) || require.extensions) {
answer = CoffeeScript.compile(code, options);
code = (ref = answer.js) != null ? ref : answer;
}
answer = CoffeeScript.compile(code, options);
code = (ref = answer.js) != null ? ref : answer;
return mainModule._compile(code, mainModule.filename);
};
@@ -152,16 +152,14 @@
}
}
CoffeeScript._compileFile = function(filename, options = {}) {
var answer, err, raw, stripped;
raw = fs.readFileSync(filename, 'utf8');
CoffeeScript._compileRawFileContent = function(raw, filename, options = {}) {
var answer, err, stripped;
// Strip the Unicode byte order mark, if this file begins with one.
stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw;
options = Object.assign({}, options, {
filename: filename,
literate: helpers.isLiterate(filename),
sourceFiles: [filename],
inlineMap: true // Always generate a source map, so that stack traces line up.
sourceFiles: [filename]
});
try {
answer = CoffeeScript.compile(stripped, options);
@@ -175,6 +173,45 @@
return answer;
};
CoffeeScript._compileFile = function(filename, options = {}) {
var raw;
raw = fs.readFileSync(filename, 'utf8');
return CoffeeScript._compileRawFileContent(raw, filename, options);
};
module.exports = CoffeeScript;
// Explicitly define all named exports so that Nodes automatic detection of
// named exports from CommonJS packages finds all of them. This enables consuming
// packages to write code like `import { compile } from 'coffeescript'`.
// Dont simplify this into a loop or similar; the `module.exports.name` part is
// essential for Nodes algorithm to successfully detect the name.
module.exports.VERSION = CoffeeScript.VERSION;
module.exports.FILE_EXTENSIONS = CoffeeScript.FILE_EXTENSIONS;
module.exports.helpers = CoffeeScript.helpers;
module.exports.registerCompiled = CoffeeScript.registerCompiled;
module.exports.compile = CoffeeScript.compile;
module.exports.tokens = CoffeeScript.tokens;
module.exports.nodes = CoffeeScript.nodes;
module.exports.register = CoffeeScript.register;
module.exports.eval = CoffeeScript.eval;
module.exports.run = CoffeeScript.run;
module.exports.transpile = CoffeeScript.transpile;
module.exports.patchStackTrace = CoffeeScript.patchStackTrace;
module.exports._compileRawFileContent = CoffeeScript._compileRawFileContent;
module.exports._compileFile = CoffeeScript._compileFile;
}).call(this);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.3.2
// Generated by CoffeeScript 2.7.0
(function() {
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat,
splice = [].splice;

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
// Generated by CoffeeScript 2.3.2
// Generated by CoffeeScript 2.7.0
(function() {
var CoffeeScript, Module, binary, child_process, ext, findExtension, fork, getRootModule, helpers, i, len, loadFile, path, ref;
var CoffeeScript, Module, binary, cacheSourceMaps, child_process, ext, findExtension, fork, getRootModule, helpers, i, len, loadFile, nodeSourceMapsSupportEnabled, patchStackTrace, path, ref, ref1;
CoffeeScript = require('./');
@@ -10,20 +10,35 @@
path = require('path');
({patchStackTrace} = CoffeeScript);
// Check if Node's built-in source map stack trace transformations are enabled.
nodeSourceMapsSupportEnabled = (typeof process !== "undefined" && process !== null) && (process.execArgv.includes('--enable-source-maps') || ((ref = process.env.NODE_OPTIONS) != null ? ref.includes('--enable-source-maps') : void 0));
if (!(Error.prepareStackTrace || nodeSourceMapsSupportEnabled)) {
cacheSourceMaps = true;
patchStackTrace();
}
// Load and run a CoffeeScript file for Node, stripping any `BOM`s.
loadFile = function(module, filename) {
var answer, options;
options = module.options || getRootModule(module).options;
answer = CoffeeScript._compileFile(filename, options);
return module._compile(answer, filename);
var js, options;
options = module.options || getRootModule(module).options || {};
// Currently `CoffeeScript.compile` caches all source maps if present. They
// are available in `getSourceMap` retrieved by `filename`.
if (cacheSourceMaps || nodeSourceMapsSupportEnabled) {
options.inlineMap = true;
}
js = CoffeeScript._compileFile(filename, options);
return module._compile(js, filename);
};
// If the installed version of Node supports `require.extensions`, register
// CoffeeScript as an extension.
if (require.extensions) {
ref = CoffeeScript.FILE_EXTENSIONS;
for (i = 0, len = ref.length; i < len; i++) {
ext = ref[i];
ref1 = CoffeeScript.FILE_EXTENSIONS;
for (i = 0, len = ref1.length; i < len; i++) {
ext = ref1[i];
require.extensions[ext] = loadFile;
}
// Patch Node's module loader to be able to handle multi-dot extensions.

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.3.2
// Generated by CoffeeScript 2.7.0
(function() {
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, replDefaults, runInContext, sawSIGINT, transpile, updateSyntaxError, vm;
@@ -29,7 +29,7 @@
})(),
historyMaxInputSize: 10240,
eval: function(input, context, filename, cb) {
var Assign, Block, Call, Code, Literal, Value, ast, err, isAsync, js, ref, ref1, referencedVars, result, token, tokens;
var Assign, Block, Call, Code, Literal, Root, Value, ast, err, isAsync, js, ref, ref1, referencedVars, result, token, tokens;
// XXX: multiline hack.
input = input.replace(/\uFF00/g, '\n');
// Node's REPL sends the input ending with a newline and then wrapped in
@@ -39,15 +39,15 @@
// Unwrap that too.
input = input.replace(/^\s*try\s*{([\s\S]*)}\s*catch.*$/m, '$1');
// Require AST nodes to do some AST manipulation.
({Block, Assign, Value, Literal, Call, Code} = require('./nodes'));
({Block, Assign, Value, Literal, Call, Code, Root} = require('./nodes'));
try {
// Tokenize the clean input.
tokens = CoffeeScript.tokens(input);
// Filter out tokens generated just to hold comments.
if (tokens.length >= 2 && tokens[0].generated && ((ref = tokens[0].comments) != null ? ref.length : void 0) !== 0 && tokens[0][1] === '' && tokens[1][0] === 'TERMINATOR') {
if (tokens.length >= 2 && tokens[0].generated && ((ref = tokens[0].comments) != null ? ref.length : void 0) !== 0 && `${tokens[0][1]}` === '' && tokens[1][0] === 'TERMINATOR') {
tokens = tokens.slice(2);
}
if (tokens.length >= 1 && tokens[tokens.length - 1].generated && ((ref1 = tokens[tokens.length - 1].comments) != null ? ref1.length : void 0) !== 0 && tokens[tokens.length - 1][1] === '') {
if (tokens.length >= 1 && tokens[tokens.length - 1].generated && ((ref1 = tokens[tokens.length - 1].comments) != null ? ref1.length : void 0) !== 0 && `${tokens[tokens.length - 1][1]}` === '') {
tokens.pop();
}
// Collect referenced variable names just like in `CoffeeScript.compile`.
@@ -63,14 +63,14 @@
return results;
})();
// Generate the AST of the tokens.
ast = CoffeeScript.nodes(tokens);
ast = CoffeeScript.nodes(tokens).body;
// Add assignment to `__` variable to force the input to be an expression.
ast = new Block([new Assign(new Value(new Literal('__')), ast, '=')]);
// Wrap the expression in a closure to support top-level `await`.
ast = new Code([], ast);
isAsync = ast.isAsync;
// Invoke the wrapping closure.
ast = new Block([new Call(ast)]);
ast = new Root(new Block([new Call(ast)]));
js = ast.compile({
bare: true,
locals: Object.keys(context),
@@ -113,8 +113,8 @@
};
addMultilineHandler = function(repl) {
var inputStream, multiline, nodeLineListener, origPrompt, outputStream, ref, rli;
({rli, inputStream, outputStream} = repl);
var inputStream, multiline, nodeLineListener, origPrompt, outputStream, ref;
({inputStream, outputStream} = repl);
// Node 0.11.12 changed API, prompt is now _prompt.
origPrompt = (ref = repl._prompt) != null ? ref : repl.prompt;
multiline = {
@@ -128,15 +128,15 @@
buffer: ''
};
// Proxy node's line listener
nodeLineListener = rli.listeners('line')[0];
rli.removeListener('line', nodeLineListener);
rli.on('line', function(cmd) {
nodeLineListener = repl.listeners('line')[0];
repl.removeListener('line', nodeLineListener);
repl.on('line', function(cmd) {
if (multiline.enabled) {
multiline.buffer += `${cmd}\n`;
rli.setPrompt(multiline.prompt);
rli.prompt(true);
repl.setPrompt(multiline.prompt);
repl.prompt(true);
} else {
rli.setPrompt(origPrompt);
repl.setPrompt(origPrompt);
nodeLineListener(cmd);
}
});
@@ -149,28 +149,28 @@
// allow arbitrarily switching between modes any time before multiple lines are entered
if (!multiline.buffer.match(/\n/)) {
multiline.enabled = !multiline.enabled;
rli.setPrompt(origPrompt);
rli.prompt(true);
repl.setPrompt(origPrompt);
repl.prompt(true);
return;
}
// no-op unless the current line is empty
if ((rli.line != null) && !rli.line.match(/^\s*$/)) {
if ((repl.line != null) && !repl.line.match(/^\s*$/)) {
return;
}
// eval, print, loop
multiline.enabled = !multiline.enabled;
rli.line = '';
rli.cursor = 0;
rli.output.cursorTo(0);
rli.output.clearLine(1);
repl.line = '';
repl.cursor = 0;
repl.output.cursorTo(0);
repl.output.clearLine(1);
// XXX: multiline hack
multiline.buffer = multiline.buffer.replace(/\n/g, '\uFF00');
rli.emit('line', multiline.buffer);
repl.emit('line', multiline.buffer);
multiline.buffer = '';
} else {
multiline.enabled = !multiline.enabled;
rli.setPrompt(multiline.initialPrompt);
rli.prompt(true);
repl.setPrompt(multiline.initialPrompt);
repl.prompt(true);
}
});
};
@@ -189,20 +189,20 @@
fs.readSync(readFd, buffer, 0, size, stat.size - size);
fs.closeSync(readFd);
// Set the history on the interpreter
repl.rli.history = buffer.toString().split('\n').reverse();
repl.history = buffer.toString().split('\n').reverse();
if (stat.size > maxSize) {
// If the history file was truncated we should pop off a potential partial line
repl.rli.history.pop();
repl.history.pop();
}
if (repl.rli.history[0] === '') {
if (repl.history[0] === '') {
// Shift off the final blank newline
repl.rli.history.shift();
repl.history.shift();
}
repl.rli.historyIndex = -1;
lastLine = repl.rli.history[0];
repl.historyIndex = -1;
lastLine = repl.history[0];
} catch (error) {}
fd = fs.openSync(filename, 'a');
repl.rli.addListener('line', function(code) {
repl.addListener('line', function(code) {
if (code && code.length && code !== '.history' && code !== '.exit' && lastLine !== code) {
// Save the latest command in the file
fs.writeSync(fd, `${code}\n`);
@@ -220,7 +220,7 @@
return repl.commands[getCommandId(repl, 'history')] = {
help: 'Show command history',
action: function() {
repl.outputStream.write(`${repl.rli.history.slice(0).reverse().join('\n')}\n`);
repl.outputStream.write(`${repl.history.slice(0).reverse().join('\n')}\n`);
return repl.displayPrompt();
}
};
@@ -257,7 +257,12 @@
try {
transpile.transpile = require('babel-core').transform;
} catch (error) {
console.error('To use --transpile with an interactive REPL, @babel/core must be installed either in the current folder or globally:\n npm install --save-dev @babel/core\nor\n npm install --global @babel/core\nAnd you must save options to configure Babel in one of the places it looks to find its options.\nSee https://coffeescript.org/#transpilation');
console.error(`To use --transpile with an interactive REPL, @babel/core must be installed either in the current folder or globally:
npm install --save-dev @babel/core
or
npm install --global @babel/core
And you must save options to configure Babel in one of the places it looks to find its options.
See https://coffeescript.org/#transpilation`);
process.exit(1);
}
}
@@ -283,7 +288,7 @@
runInContext(opts.prelude, repl.context, 'prelude');
}
repl.on('exit', function() {
if (!repl.rli.closed) {
if (!repl.closed) {
return repl.outputStream.write('\n');
}
});

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.3.2
// Generated by CoffeeScript 2.7.0
(function() {
// The CoffeeScript language has a good deal of optional syntax, implicit syntax,
// and shorthand syntax. This can greatly complicate a grammar and bloat
@@ -6,10 +6,11 @@
// a series of passes over the token stream, using this **Rewriter** to convert
// shorthand into the unambiguous long form, add implicit indentation and
// parentheses, and generally clean things up.
var BALANCED_PAIRS, CALL_CLOSERS, CONTROL_IN_IMPLICIT, DISCARDED, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, moveComments, right, throwSyntaxError,
indexOf = [].indexOf;
var BALANCED_PAIRS, CALL_CLOSERS, CONTROL_IN_IMPLICIT, DISCARDED, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, UNFINISHED, extractAllCommentTokens, generate, k, left, len, moveComments, right, throwSyntaxError,
indexOf = [].indexOf,
hasProp = {}.hasOwnProperty;
({throwSyntaxError} = require('./helpers'));
({throwSyntaxError, extractAllCommentTokens} = require('./helpers'));
// Move attached comments from one token to another.
moveComments = function(fromToken, toToken) {
@@ -86,11 +87,11 @@
this.normalizeLines();
this.tagPostfixConditionals();
this.addImplicitBracesAndParens();
this.addParensToChainedDoIife();
this.rescueStowawayComments();
this.addLocationDataToGeneratedTokens();
this.enforceValidCSXAttributes();
this.fixOutdentLocationData();
this.enforceValidJSXAttributes();
this.fixIndentationLocationData();
this.exposeTokenDataToGrammar();
if (typeof process !== "undefined" && process !== null ? (ref1 = process.env) != null ? ref1.DEBUG_REWRITTEN_TOKEN_STREAM : void 0 : void 0) {
if (process.env.DEBUG_TOKEN_STREAM) {
console.log('Rewritten token stream:');
@@ -196,16 +197,23 @@
// The lexer has tagged the opening bracket of an indexing operation call.
// Match it with its paired close.
closeOpenIndexes() {
var action, condition;
var action, condition, startToken;
startToken = null;
condition = function(token, i) {
var ref;
return (ref = token[0]) === ']' || ref === 'INDEX_END';
};
action = function(token, i) {
return token[0] = 'INDEX_END';
if (this.tokens.length >= i && this.tokens[i + 1][0] === ':') {
startToken[0] = '[';
return token[0] = ']';
} else {
return token[0] = 'INDEX_END';
}
};
return this.scanTokens(function(token, i) {
if (token[0] === 'INDEX_START') {
startToken = token;
this.detectEnd(i + 1, condition, action);
}
return 1;
@@ -281,7 +289,7 @@
stack = [];
start = null;
return this.scanTokens(function(token, i, tokens) {
var endImplicitCall, endImplicitObject, forward, implicitObjectContinues, inControlFlow, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, isImplicit, isImplicitCall, isImplicitObject, k, newLine, nextTag, nextToken, offset, prevTag, prevToken, ref, ref1, ref2, s, sameLine, stackIdx, stackItem, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
var endImplicitCall, endImplicitObject, forward, implicitObjectContinues, implicitObjectIndent, inControlFlow, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, isImplicit, isImplicitCall, isImplicitObject, k, newLine, nextTag, nextToken, offset, preContinuationLineIndent, preObjectToken, prevTag, prevToken, ref, ref1, ref2, ref3, ref4, ref5, s, sameLine, stackIdx, stackItem, stackNext, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startIndex, startTag, startsLine, tag;
[tag] = token;
[prevTag] = prevToken = i > 0 ? tokens[i - 1] : [];
[nextTag] = nextToken = i < tokens.length - 1 ? tokens[i + 1] : [];
@@ -335,7 +343,7 @@
tokens.splice(i, 0, generate('CALL_END', ')', ['', 'end of input', token[2]], prevToken));
return i += 1;
};
startImplicitObject = function(idx, startsLine = true) {
startImplicitObject = function(idx, {startsLine = true, continuationLineIndent} = {}) {
var val;
stack.push([
'{',
@@ -343,7 +351,8 @@
{
sameLine: true,
startsLine: startsLine,
ours: true
ours: true,
continuationLineIndent: continuationLineIndent
}
]);
val = new String('{');
@@ -467,9 +476,9 @@
// if f(a: 1)
// which is probably always unintended.
// Furthermore dont allow this in literal arrays, as
// that creates grammatical ambiguities.
if (indexOf.call(IMPLICIT_FUNC, tag) >= 0 && this.indexOfTag(i + 1, 'INDENT') > -1 && this.looksObjectish(i + 2) && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])) {
// Furthermore dont allow this in the first line of a literal array
// or explicit object, as that creates grammatical ambiguities (#5368).
if (indexOf.call(IMPLICIT_FUNC, tag) >= 0 && this.indexOfTag(i + 1, 'INDENT') > -1 && this.looksObjectish(i + 2) && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL']) && !(((ref1 = (s = (ref2 = stackTop()) != null ? ref2[0] : void 0)) === '{' || ref1 === '[') && !isImplicit(stackTop()) && this.findTagsBackwards(i, s))) {
startImplicitCall(i + 1);
stack.push(['INDENT', i + 2]);
return forward(3);
@@ -478,25 +487,37 @@
if (tag === ':') {
// Go back to the (implicit) start of the object.
s = (function() {
var ref1;
var ref3;
switch (false) {
case ref1 = this.tag(i - 1), indexOf.call(EXPRESSION_END, ref1) < 0:
return start[1];
case ref3 = this.tag(i - 1), indexOf.call(EXPRESSION_END, ref3) < 0:
[startTag, startIndex] = start;
if (startTag === '[' && startIndex > 0 && this.tag(startIndex - 1) === '@' && !tokens[startIndex - 1].spaced) {
return startIndex - 1;
} else {
return startIndex;
}
break;
case this.tag(i - 2) !== '@':
return i - 2;
default:
return i - 1;
}
}).call(this);
startsLine = s <= 0 || (ref1 = this.tag(s - 1), indexOf.call(LINEBREAKS, ref1) >= 0) || tokens[s - 1].newLine;
startsLine = s <= 0 || (ref3 = this.tag(s - 1), indexOf.call(LINEBREAKS, ref3) >= 0) || tokens[s - 1].newLine;
// Are we just continuing an already declared object?
// Including the case where we indent on the line after an explicit '{'.
if (stackTop()) {
[stackTag, stackIdx] = stackTop();
if ((stackTag === '{' || stackTag === 'INDENT' && this.tag(stackIdx - 1) === '{') && (startsLine || this.tag(s - 1) === ',' || this.tag(s - 1) === '{')) {
stackNext = stack[stack.length - 2];
if ((stackTag === '{' || stackTag === 'INDENT' && (stackNext != null ? stackNext[0] : void 0) === '{' && !isImplicit(stackNext) && this.findTagsBackwards(stackIdx - 1, ['{'])) && (startsLine || this.tag(s - 1) === ',' || this.tag(s - 1) === '{') && (ref4 = this.tag(s - 1), indexOf.call(UNFINISHED, ref4) < 0)) {
return forward(1);
}
}
startImplicitObject(s, !!startsLine);
preObjectToken = i > 1 ? tokens[i - 2] : [];
startImplicitObject(s, {
startsLine: !!startsLine,
continuationLineIndent: preObjectToken.continuationLineIndent
});
return forward(2);
}
// End implicit calls when chaining method calls
@@ -526,6 +547,13 @@
}
}
}
// End indented-continuation-line implicit objects once that indentation is over.
if (tag === 'TERMINATOR' && token.endsContinuationLineIndentation) {
({preContinuationLineIndent} = token.endsContinuationLineIndentation);
while (inImplicitObject() && ((implicitObjectIndent = stackTop()[2].continuationLineIndent) != null) && implicitObjectIndent > preContinuationLineIndent) {
endImplicitObject();
}
}
newLine = prevTag === 'OUTDENT' || prevToken.newLine;
if (indexOf.call(IMPLICIT_END, tag) >= 0 || (indexOf.call(CALL_CLOSERS, tag) >= 0 && newLine) || ((tag === '..' || tag === '...') && this.findTagsBackwards(i, ["INDEX_START"]))) {
while (inImplicit()) {
@@ -562,7 +590,7 @@
// f a, b: c, d: e, f, g: h: i, j
if (tag === ',' && !this.looksObjectish(i + 1) && inImplicitObject() && !((ref2 = this.tag(i + 2)) === 'FOROF' || ref2 === 'FORIN') && (nextTag !== 'TERMINATOR' || !this.looksObjectish(i + 2))) {
if (tag === ',' && !this.looksObjectish(i + 1) && inImplicitObject() && !((ref5 = this.tag(i + 2)) === 'FOROF' || ref5 === 'FORIN') && (nextTag !== 'TERMINATOR' || !this.looksObjectish(i + 2))) {
// When nextTag is OUTDENT the comma is insignificant and
// should just be ignored so embed it in the implicit object.
@@ -577,11 +605,11 @@
});
}
// Make sure only strings and wrapped expressions are used in CSX attributes.
enforceValidCSXAttributes() {
// Make sure only strings and wrapped expressions are used in JSX attributes.
enforceValidJSXAttributes() {
return this.scanTokens(function(token, i, tokens) {
var next, ref;
if (token.csxColon) {
if (token.jsxColon) {
next = tokens[i + 1];
if ((ref = next[0]) !== 'STRING_START' && ref !== 'STRING' && ref !== '(') {
throwSyntaxError('expected wrapped or quoted JSX attribute', next[2]);
@@ -595,13 +623,24 @@
// lost into the ether, find comments attached to doomed tokens and move them
// to a token that will make it to the other side.
rescueStowawayComments() {
var insertPlaceholder, shiftCommentsBackward, shiftCommentsForward;
var dontShiftForward, insertPlaceholder, shiftCommentsBackward, shiftCommentsForward;
insertPlaceholder = function(token, j, tokens, method) {
if (tokens[j][0] !== 'TERMINATOR') {
tokens[method](generate('TERMINATOR', '\n', tokens[j]));
}
return tokens[method](generate('JS', '', tokens[j], token));
};
dontShiftForward = function(i, tokens) {
var j, ref;
j = i + 1;
while (j !== tokens.length && (ref = tokens[j][0], indexOf.call(DISCARDED, ref) >= 0)) {
if (tokens[j][0] === 'INTERPOLATION_END') {
return true;
}
j++;
}
return false;
};
shiftCommentsForward = function(token, i, tokens) {
var comment, j, k, len, ref, ref1, ref2;
// Find the next surviving token and attach this tokens comments to it,
@@ -671,7 +710,7 @@
if (token.comments.length !== 0) {
shiftCommentsForward(token, i, tokens);
}
} else {
} else if (!dontShiftForward(i, tokens)) {
// If any of this tokens comments start a line—theres only
// whitespace between the preceding newline and the start of the
// comment—and this isnt one of the special `JS` tokens, then
@@ -708,31 +747,42 @@
// Add location data to all tokens generated by the rewriter.
addLocationDataToGeneratedTokens() {
return this.scanTokens(function(token, i, tokens) {
var column, line, nextLocation, prevLocation, ref, ref1;
var column, line, nextLocation, prevLocation, rangeIndex, ref, ref1;
if (token[2]) {
return 1;
}
if (!(token.generated || token.explicit)) {
return 1;
}
if (token.fromThen && token[0] === 'INDENT') {
token[2] = token.origin[2];
return 1;
}
if (token[0] === '{' && (nextLocation = (ref = tokens[i + 1]) != null ? ref[2] : void 0)) {
({
first_line: line,
first_column: column
first_column: column,
range: [rangeIndex]
} = nextLocation);
} else if (prevLocation = (ref1 = tokens[i - 1]) != null ? ref1[2] : void 0) {
({
last_line: line,
last_column: column
last_column: column,
range: [, rangeIndex]
} = prevLocation);
column += 1;
} else {
line = column = 0;
rangeIndex = 0;
}
token[2] = {
first_line: line,
first_column: column,
last_line: line,
last_column: column
last_column: column,
last_line_exclusive: line,
last_column_exclusive: column,
range: [rangeIndex, rangeIndex]
};
return 1;
});
@@ -741,63 +791,104 @@
// `OUTDENT` tokens should always be positioned at the last character of the
// previous token, so that AST nodes ending in an `OUTDENT` token end up with a
// location corresponding to the last “real” token under the node.
fixOutdentLocationData() {
fixIndentationLocationData() {
var findPrecedingComment;
if (this.allComments == null) {
this.allComments = extractAllCommentTokens(this.tokens);
}
findPrecedingComment = (token, {afterPosition, indentSize, first, indented}) => {
var comment, k, l, lastMatching, matches, ref, ref1, tokenStart;
tokenStart = token[2].range[0];
matches = function(comment) {
if (comment.outdented) {
if (!((indentSize != null) && comment.indentSize > indentSize)) {
return false;
}
}
if (indented && !comment.indented) {
return false;
}
if (!(comment.locationData.range[0] < tokenStart)) {
return false;
}
if (!(comment.locationData.range[0] > afterPosition)) {
return false;
}
return true;
};
if (first) {
lastMatching = null;
ref = this.allComments;
for (k = ref.length - 1; k >= 0; k += -1) {
comment = ref[k];
if (matches(comment)) {
lastMatching = comment;
} else if (lastMatching) {
return lastMatching;
}
}
return lastMatching;
}
ref1 = this.allComments;
for (l = ref1.length - 1; l >= 0; l += -1) {
comment = ref1[l];
if (matches(comment)) {
return comment;
}
}
return null;
};
return this.scanTokens(function(token, i, tokens) {
var prevLocationData;
if (!(token[0] === 'OUTDENT' || (token.generated && token[0] === 'CALL_END') || (token.generated && token[0] === '}'))) {
var isIndent, nextToken, nextTokenIndex, precedingComment, prevLocationData, prevToken, ref, ref1, ref2, useNextToken;
if (!(((ref = token[0]) === 'INDENT' || ref === 'OUTDENT') || (token.generated && token[0] === 'CALL_END' && !((ref1 = token.data) != null ? ref1.closingTagNameToken : void 0)) || (token.generated && token[0] === '}'))) {
return 1;
}
prevLocationData = tokens[i - 1][2];
isIndent = token[0] === 'INDENT';
prevToken = (ref2 = token.prevToken) != null ? ref2 : tokens[i - 1];
prevLocationData = prevToken[2];
// addLocationDataToGeneratedTokens() set the outdents location data
// to the preceding tokens, but in order to detect comments inside an
// empty "block" we want to look for comments preceding the next token.
useNextToken = token.explicit || token.generated;
if (useNextToken) {
nextToken = token;
nextTokenIndex = i;
while ((nextToken.explicit || nextToken.generated) && nextTokenIndex !== tokens.length - 1) {
nextToken = tokens[nextTokenIndex++];
}
}
precedingComment = findPrecedingComment(useNextToken ? nextToken : token, {
afterPosition: prevLocationData.range[0],
indentSize: token.indentSize,
first: isIndent,
indented: useNextToken
});
if (isIndent) {
if (!(precedingComment != null ? precedingComment.newLine : void 0)) {
return 1;
}
}
if (token.generated && token[0] === 'CALL_END' && (precedingComment != null ? precedingComment.indented : void 0)) {
// We dont want e.g. an implicit call at the end of an `if` condition to
// include a following indented comment.
return 1;
}
if (precedingComment != null) {
prevLocationData = precedingComment.locationData;
}
token[2] = {
first_line: prevLocationData.last_line,
first_column: prevLocationData.last_column,
first_line: precedingComment != null ? prevLocationData.first_line : prevLocationData.last_line,
first_column: precedingComment != null ? isIndent ? 0 : prevLocationData.first_column : prevLocationData.last_column,
last_line: prevLocationData.last_line,
last_column: prevLocationData.last_column
last_column: prevLocationData.last_column,
last_line_exclusive: prevLocationData.last_line_exclusive,
last_column_exclusive: prevLocationData.last_column_exclusive,
range: isIndent && (precedingComment != null) ? [prevLocationData.range[0] - precedingComment.indentSize, prevLocationData.range[1]] : prevLocationData.range
};
return 1;
});
}
// Add parens around a `do` IIFE followed by a chained `.` so that the
// chaining applies to the executed function rather than the function
// object (see #3736)
addParensToChainedDoIife() {
var action, condition, doIndex;
condition = function(token, i) {
return this.tag(i - 1) === 'OUTDENT';
};
action = function(token, i) {
var ref;
if (ref = token[0], indexOf.call(CALL_CLOSERS, ref) < 0) {
return;
}
this.tokens.splice(doIndex, 0, generate('(', '(', this.tokens[doIndex]));
return this.tokens.splice(i + 1, 0, generate(')', ')', this.tokens[i]));
};
doIndex = null;
return this.scanTokens(function(token, i, tokens) {
var glyphIndex, ref;
if (token[1] !== 'do') {
return 1;
}
doIndex = i;
glyphIndex = i + 1;
if (this.tag(i + 1) === 'PARAM_START') {
glyphIndex = null;
this.detectEnd(i + 1, function(token, i) {
return this.tag(i - 1) === 'PARAM_END';
}, function(token, i) {
return glyphIndex = i;
});
}
if (!((glyphIndex != null) && ((ref = this.tag(glyphIndex)) === '->' || ref === '=>') && this.tag(glyphIndex + 1) === 'INDENT')) {
return 1;
}
this.detectEnd(glyphIndex + 1, condition, action);
return 2;
});
}
// Because our grammar is LALR(1), it cant handle some single-line
// expressions that lack ending delimiters. The **Rewriter** adds the implicit
// blocks, so it doesnt need to. To keep the grammar clean and tidy, trailing
@@ -846,7 +937,7 @@
return i + 2;
};
return this.scanTokens(function(token, i, tokens) {
var conditionTag, j, k, ref, ref1, tag;
var conditionTag, j, k, ref, ref1, ref2, tag;
[tag] = token;
conditionTag = (tag === '->' || tag === '=>') && this.findTagsBackwards(i, ['IF', 'WHILE', 'FOR', 'UNTIL', 'SWITCH', 'WHEN', 'LEADING_WHEN', '[', 'INDEX_START']) && !(this.findTagsBackwards(i, ['THEN', '..', '...']));
if (tag === 'TERMINATOR') {
@@ -855,6 +946,10 @@
return 1;
}
if (ref = this.tag(i + 1), indexOf.call(EXPRESSION_CLOSE, ref) >= 0) {
if (token[1] === ';' && this.tag(i + 1) === 'OUTDENT') {
tokens[i + 1].prevToken = token;
moveComments(token, tokens[i + 1]);
}
tokens.splice(i, 1);
return 0;
}
@@ -868,7 +963,7 @@
return 2 + j;
}
}
if ((tag === '->' || tag === '=>') && (this.tag(i + 1) === ',' || this.tag(i + 1) === '.' && token.newLine)) {
if ((tag === '->' || tag === '=>') && (((ref2 = this.tag(i + 1)) === ',' || ref2 === ']') || this.tag(i + 1) === '.' && token.newLine)) {
[indent, outdent] = this.indentation(tokens[i]);
tokens.splice(i + 1, 0, indent, outdent);
return 1;
@@ -927,6 +1022,30 @@
});
}
// For tokens with extra data, we want to make that data visible to the grammar
// by wrapping the token value as a String() object and setting the data as
// properties of that object. The grammar should then be responsible for
// cleaning this up for the node constructor: unwrapping the token value to a
// primitive string and separately passing any expected token data properties
exposeTokenDataToGrammar() {
return this.scanTokens(function(token, i) {
var key, ref, ref1, val;
if (token.generated || (token.data && Object.keys(token.data).length !== 0)) {
token[1] = new String(token[1]);
ref1 = (ref = token.data) != null ? ref : {};
for (key in ref1) {
if (!hasProp.call(ref1, key)) continue;
val = ref1[key];
token[1][key] = val;
}
if (token.generated) {
token[1].generated = true;
}
}
return 1;
});
}
// Generate the indentation tokens, based on another token on the same line.
indentation(origin) {
var indent, outdent;
@@ -959,7 +1078,7 @@
// ---------
// List of the token pairs that must be balanced.
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END'], ['STRING_START', 'STRING_END'], ['REGEX_START', 'REGEX_END']];
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END'], ['STRING_START', 'STRING_END'], ['INTERPOLATION_START', 'INTERPOLATION_END'], ['REGEX_START', 'REGEX_END']];
// The inverse mappings of `BALANCED_PAIRS` were trying to fix up, so we can
// look things up from either end.
@@ -983,7 +1102,7 @@
IMPLICIT_FUNC = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
// If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
IMPLICIT_CALL = ['IDENTIFIER', 'CSX_TAG', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN', 'STRING', 'STRING_START', 'REGEX', 'REGEX_START', 'JS', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'UNDEFINED', 'NULL', 'BOOL', 'UNARY', 'YIELD', 'AWAIT', 'UNARY_MATH', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'];
IMPLICIT_CALL = ['IDENTIFIER', 'JSX_TAG', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN', 'STRING', 'STRING_START', 'REGEX', 'REGEX_START', 'JS', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'DYNAMIC_IMPORT', 'IMPORT_META', 'NEW_TARGET', 'UNDEFINED', 'NULL', 'BOOL', 'UNARY', 'DO', 'DO_IIFE', 'YIELD', 'AWAIT', 'UNARY_MATH', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'];
IMPLICIT_UNSPACED_CALL = ['+', '-'];
@@ -1011,6 +1130,9 @@
// `STRING_START` isnt on this list because its `locationData` matches that of
// the node that becomes `StringWithInterpolations`, and therefore
// `addDataToNode` attaches `STRING_START`s tokens to that node.
DISCARDED = ['(', ')', '[', ']', '{', '}', '.', '..', '...', ',', '=', '++', '--', '?', 'AS', 'AWAIT', 'CALL_START', 'CALL_END', 'DEFAULT', 'ELSE', 'EXTENDS', 'EXPORT', 'FORIN', 'FOROF', 'FORFROM', 'IMPORT', 'INDENT', 'INDEX_SOAK', 'LEADING_WHEN', 'OUTDENT', 'PARAM_END', 'REGEX_START', 'REGEX_END', 'RETURN', 'STRING_END', 'THROW', 'UNARY', 'YIELD'].concat(IMPLICIT_UNSPACED_CALL.concat(IMPLICIT_END.concat(CALL_CLOSERS.concat(CONTROL_IN_IMPLICIT))));
DISCARDED = ['(', ')', '[', ']', '{', '}', ':', '.', '..', '...', ',', '=', '++', '--', '?', 'AS', 'AWAIT', 'CALL_START', 'CALL_END', 'DEFAULT', 'DO', 'DO_IIFE', 'ELSE', 'EXTENDS', 'EXPORT', 'FORIN', 'FOROF', 'FORFROM', 'IMPORT', 'INDENT', 'INDEX_SOAK', 'INTERPOLATION_START', 'INTERPOLATION_END', 'LEADING_WHEN', 'OUTDENT', 'PARAM_END', 'REGEX_START', 'REGEX_END', 'RETURN', 'STRING_END', 'THROW', 'UNARY', 'YIELD'].concat(IMPLICIT_UNSPACED_CALL.concat(IMPLICIT_END.concat(CALL_CLOSERS.concat(CONTROL_IN_IMPLICIT))));
// Tokens that, when appearing at the end of a line, suppress a following TERMINATOR/INDENT token
exports.UNFINISHED = UNFINISHED = ['\\', '.', '?.', '?::', 'UNARY', 'DO', 'DO_IIFE', 'MATH', 'UNARY_MATH', '+', '-', '**', 'SHIFT', 'RELATION', 'COMPARE', '&', '^', '|', '&&', '||', 'BIN?', 'EXTENDS'];
}).call(this);

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.3.2
// Generated by CoffeeScript 2.7.0
(function() {
// The **Scope** class regulates lexical scoping within CoffeeScript. As you
// generate code, you create a tree of scopes in the same shape as the nested

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 2.3.2
// Generated by CoffeeScript 2.7.0
(function() {
// Source maps allow JavaScript runtimes to match running JavaScript back to
// the original source code that corresponds to it. This can be minified
@@ -53,10 +53,10 @@
// SourceMap
// ---------
// Maps locations in a single generated JavaScript file back to locations in
// Maps locations in a single generated JavaScript file back to locations in
// the original CoffeeScript source file.
// This is intentionally agnostic towards how a source map might be represented on
// This is intentionally agnostic towards how a source map might be represented on
// disk. Once the compiler is ready to produce a "v3"-style source map, we can walk
// through the arrays of line and column buffer to produce it.
class SourceMap {
@@ -85,10 +85,20 @@
return lineMap && lineMap.sourceLocation(column);
}
static registerCompiled(filename, source, sourcemap) {
if (sourcemap != null) {
return SourceMap.sourceMaps[filename] = sourcemap;
}
}
static getSourceMap(filename) {
return SourceMap.sourceMaps[filename];
}
// V3 SourceMap Generation
// -----------------------
// Builds up a V3 source map, returning the generated JSON as a string.
// Builds up a V3 source map, returning the generated JSON as a string.
// `options.sourceRoot` may be used to specify the sourceRoot written to the source
// map. Also, `options.sourceFiles` and `options.generatedFile` may be passed to
// set "sources" and "file", respectively.
@@ -183,6 +193,14 @@
};
// Caching
// -------
// A static source maps cache `filename`: `map`. These are used for transforming
// stack traces and are currently set in `CoffeeScript.compile` for all files
// compiled with the source maps option.
SourceMap.sourceMaps = Object.create(null);
// Base64 VLQ Encoding
// -------------------

10411
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
"compiler"
],
"author": "Jeremy Ashkenas",
"version": "2.3.2",
"version": "2.7.0",
"license": "MIT",
"engines": {
"node": ">=6"
@@ -17,7 +17,8 @@
"lib": "./lib/coffeescript"
},
"main": "./lib/coffeescript/index",
"browser": "./lib/coffeescript/browser",
"module": "./lib/coffeescript-browser-compiler-modern/coffeescript.js",
"browser": "./lib/coffeescript-browser-compiler-legacy/coffeescript.js",
"bin": {
"coffee": "./bin/coffee",
"cake": "./bin/cake"
@@ -39,16 +40,16 @@
"url": "git://github.com/jashkenas/coffeescript.git"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"babel-preset-minify": "^0.4.3",
"codemirror": "^5.39.2",
"docco": "~0.8.0",
"highlight.js": "~9.12.0",
"jison": ">=0.4.18",
"markdown-it": "~8.4.2",
"underscore": "~1.9.1",
"webpack": "~4.17.2"
},
"dependencies": {}
"@babel/core": "~7.17.8",
"@babel/preset-env": "~7.16.11",
"babel-preset-minify": "~0.5.1",
"codemirror": "~5.65.2",
"docco": "~0.9.1",
"highlight.js": "~11.5.0",
"jison": "~0.4.18",
"markdown-it": "~12.3.2",
"puppeteer": "~13.5.2",
"underscore": "~1.13.2",
"webpack": "~5.71.0"
}
}

View File

@@ -58,7 +58,7 @@ CoffeeScript.load = (url, callback, options = {}, hold = false) ->
# Activate CoffeeScript in the browser by having it compile and evaluate
# all script tags with a content-type of `text/coffeescript`.
# This happens on page load.
runScripts = ->
CoffeeScript.runScripts = ->
scripts = window.document.getElementsByTagName 'script'
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript']
coffees = (s for s in scripts when s.type in coffeetypes)
@@ -96,7 +96,12 @@ runScripts = ->
execute()
# Listen for window load, both in decent browsers and in IE.
if window.addEventListener
window.addEventListener 'DOMContentLoaded', runScripts, no
else
window.attachEvent 'onload', runScripts
# Only attach this event handler on startup for the
# non-ES module version of the browser compiler, to preserve
# backward compatibility while letting the ES module version
# be importable without side effects.
if this is window
if window.addEventListener
window.addEventListener 'DOMContentLoaded', CoffeeScript.runScripts, no
else
window.attachEvent 'onload', CoffeeScript.runScripts

View File

@@ -19,6 +19,12 @@ exports.FILE_EXTENSIONS = FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.m
# Expose helpers for testing.
exports.helpers = helpers
{getSourceMap, registerCompiled} = SourceMap
# This is exported to enable an external module to implement caching of
# sourcemaps. This is used only when `patchStackTrace` has been called to adjust
# stack traces for files with cached source maps.
exports.registerCompiled = registerCompiled
# Function that allows for btoa in both nodejs and the browser.
base64encode = (src) -> switch
when typeof Buffer is 'function'
@@ -43,17 +49,6 @@ withPrettyErrors = (fn) ->
throw err if typeof code isnt 'string' # Support `CoffeeScript.nodes(tokens)`.
throw helpers.updateSyntaxError err, code, options.filename
# For each compiled file, save its source in memory in case we need to
# recompile it later. We might need to recompile if the first compilation
# didnt create a source map (faster) but something went wrong and we need
# a stack trace. Assuming that most of the time, code isnt throwing
# exceptions, its probably more efficient to compile twice only when we
# need a stack trace, rather than always generating a source map even when
# its not likely to be used. Save in form of `filename`: [`(source)`]
sources = {}
# Also save source maps if generated, in form of `(source)`: [`(source map)`].
sourceMaps = {}
# Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
#
# If `options.sourceMap` is specified, then `options.filename` must also be
@@ -67,16 +62,12 @@ sourceMaps = {}
exports.compile = compile = withPrettyErrors (code, options = {}) ->
# Clone `options`, to avoid mutating the `options` object passed in.
options = Object.assign {}, options
# Always generate a source map if no filename is passed in, since without a
# a filename we have no way to retrieve this source later in the event that
# we need to recompile it to get a source map for `prepareStackTrace`.
generateSourceMap = options.sourceMap or options.inlineMap or not options.filename?
filename = options.filename or '<anonymous>'
filename = options.filename or helpers.anonymousFileName()
checkShebangLine filename, code
sources[filename] ?= []
sources[filename].push code
map = new SourceMap if generateSourceMap
tokens = lexer.tokenize code, options
@@ -94,7 +85,28 @@ exports.compile = compile = withPrettyErrors (code, options = {}) ->
options.bare = yes
break
fragments = parser.parse(tokens).compileToFragments options
nodes = parser.parse tokens
# If all that was requested was a POJO representation of the nodes, e.g.
# the abstract syntax tree (AST), we can stop now and just return that
# (after fixing the location data for the root/`File`»`Program` node,
# which mightve gotten misaligned from the original source due to the
# `clean` function in the lexer).
if options.ast
nodes.allCommentTokens = helpers.extractAllCommentTokens tokens
sourceCodeNumberOfLines = (code.match(/\r?\n/g) or '').length + 1
sourceCodeLastLine = /.*$/.exec(code)[0] # `.*` matches all but line break characters.
ast = nodes.ast options
range = [0, code.length]
ast.start = ast.program.start = range[0]
ast.end = ast.program.end = range[1]
ast.range = ast.program.range = range
ast.loc.start = ast.program.loc.start = {line: 1, column: 0}
ast.loc.end.line = ast.program.loc.end.line = sourceCodeNumberOfLines
ast.loc.end.column = ast.program.loc.end.column = sourceCodeLastLine.length
ast.tokens = tokens
return ast
fragments = nodes.compileToFragments options
currentLine = 0
currentLine += 1 if options.header
@@ -126,8 +138,6 @@ exports.compile = compile = withPrettyErrors (code, options = {}) ->
if generateSourceMap
v3SourceMap = map.generate options, code
sourceMaps[filename] ?= []
sourceMaps[filename].push map
if options.transpile
if typeof options.transpile isnt 'object'
@@ -155,9 +165,11 @@ exports.compile = compile = withPrettyErrors (code, options = {}) ->
if options.inlineMap
encoded = base64encode JSON.stringify v3SourceMap
sourceMapDataURI = "//# sourceMappingURL=data:application/json;base64,#{encoded}"
sourceURL = "//# sourceURL=#{options.filename ? 'coffeescript'}"
sourceURL = "//# sourceURL=#{filename}"
js = "#{js}\n#{sourceMapDataURI}\n#{sourceURL}"
registerCompiled filename, code, map
if options.sourceMap
{
js
@@ -175,10 +187,8 @@ exports.tokens = withPrettyErrors (code, options) ->
# return the AST. You can then compile it by calling `.compile()` on the root,
# or traverse it by using `.traverseChildren()` with a callback.
exports.nodes = withPrettyErrors (source, options) ->
if typeof source is 'string'
parser.parse lexer.tokenize source, options
else
parser.parse source
source = lexer.tokenize source, options if typeof source is 'string'
parser.parse source
# This file used to export these methods; leave stubs that throw warnings
# instead. These methods have been moved into `index.coffee` to provide
@@ -195,6 +205,10 @@ lexer = new Lexer
# thin wrapper around it, compatible with the Jison API. We can then pass it
# directly as a “Jison lexer.”
parser.lexer =
yylloc:
range: []
options:
ranges: yes
lex: ->
token = parser.tokens[@pos++]
if token
@@ -236,111 +250,77 @@ parser.yy.parseError = (message, {token}) ->
# from the lexer.
helpers.throwSyntaxError "unexpected #{errorText}", errorLoc
# Based on http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js
# Modified to handle sourceMap
formatSourcePosition = (frame, getSourceMapping) ->
filename = undefined
fileLocation = ''
exports.patchStackTrace = ->
# Based on http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js
# Modified to handle sourceMap
formatSourcePosition = (frame, getSourceMapping) ->
filename = undefined
fileLocation = ''
if frame.isNative()
fileLocation = "native"
else
if frame.isEval()
filename = frame.getScriptNameOrSourceURL()
fileLocation = "#{frame.getEvalOrigin()}, " unless filename
if frame.isNative()
fileLocation = "native"
else
filename = frame.getFileName()
filename or= "<anonymous>"
line = frame.getLineNumber()
column = frame.getColumnNumber()
# Check for a sourceMap position
source = getSourceMapping filename, line, column
fileLocation =
if source
"#{filename}:#{source[0]}:#{source[1]}"
if frame.isEval()
filename = frame.getScriptNameOrSourceURL()
fileLocation = "#{frame.getEvalOrigin()}, " unless filename
else
"#{filename}:#{line}:#{column}"
filename = frame.getFileName()
functionName = frame.getFunctionName()
isConstructor = frame.isConstructor()
isMethodCall = not (frame.isToplevel() or isConstructor)
filename or= "<anonymous>"
if isMethodCall
methodName = frame.getMethodName()
typeName = frame.getTypeName()
line = frame.getLineNumber()
column = frame.getColumnNumber()
if functionName
tp = as = ''
if typeName and functionName.indexOf typeName
tp = "#{typeName}."
if methodName and functionName.indexOf(".#{methodName}") isnt functionName.length - methodName.length - 1
as = " [as #{methodName}]"
# Check for a sourceMap position
source = getSourceMapping filename, line, column
fileLocation =
if source
"#{filename}:#{source[0]}:#{source[1]}"
else
"#{filename}:#{line}:#{column}"
"#{tp}#{functionName}#{as} (#{fileLocation})"
functionName = frame.getFunctionName()
isConstructor = frame.isConstructor()
isMethodCall = not (frame.isToplevel() or isConstructor)
if isMethodCall
methodName = frame.getMethodName()
typeName = frame.getTypeName()
if functionName
tp = as = ''
if typeName and functionName.indexOf typeName
tp = "#{typeName}."
if methodName and functionName.indexOf(".#{methodName}") isnt functionName.length - methodName.length - 1
as = " [as #{methodName}]"
"#{tp}#{functionName}#{as} (#{fileLocation})"
else
"#{typeName}.#{methodName or '<anonymous>'} (#{fileLocation})"
else if isConstructor
"new #{functionName or '<anonymous>'} (#{fileLocation})"
else if functionName
"#{functionName} (#{fileLocation})"
else
"#{typeName}.#{methodName or '<anonymous>'} (#{fileLocation})"
else if isConstructor
"new #{functionName or '<anonymous>'} (#{fileLocation})"
else if functionName
"#{functionName} (#{fileLocation})"
else
fileLocation
fileLocation
getSourceMap = (filename, line, column) ->
# Skip files that we didnt compile, like Node system files that appear in
# the stack trace, as they never have source maps.
return null unless filename is '<anonymous>' or filename.slice(filename.lastIndexOf('.')) in FILE_EXTENSIONS
if filename isnt '<anonymous>' and sourceMaps[filename]?
return sourceMaps[filename][sourceMaps[filename].length - 1]
# CoffeeScript compiled in a browser or via `CoffeeScript.compile` or `.run`
# may get compiled with `options.filename` thats missing, which becomes
# `<anonymous>`; but the runtime might request the stack trace with the
# filename of the script file. See if we have a source map cached under
# `<anonymous>` that matches the error.
else if sourceMaps['<anonymous>']?
# Work backwards from the most recent anonymous source maps, until we find
# one that works. This isnt foolproof; there is a chance that multiple
# source maps will have line/column pairs that match. But we have no other
# way to match them. `frame.getFunction().toString()` doesnt always work,
# and its not foolproof either.
for map in sourceMaps['<anonymous>'] by -1
sourceLocation = map.sourceLocation [line - 1, column - 1]
return map if sourceLocation?[0]? and sourceLocation[1]?
# If all else fails, recompile this source to get a source map. We need the
# previous section (for `<anonymous>`) despite this option, because after it
# gets compiled we will still need to look it up from
# `sourceMaps['<anonymous>']` in order to find and return it. Thats why we
# start searching from the end in the previous block, because most of the
# time the source map we want is the last one.
if sources[filename]?
answer = compile sources[filename][sources[filename].length - 1],
filename: filename
sourceMap: yes
literate: helpers.isLiterate filename
answer.sourceMap
else
null
# Based on [michaelficarra/CoffeeScriptRedux](http://goo.gl/ZTx1p)
# NodeJS / V8 have no support for transforming positions in stack traces using
# sourceMap, so we must monkey-patch Error to display CoffeeScript source
# positions.
Error.prepareStackTrace = (err, stack) ->
getSourceMapping = (filename, line, column) ->
sourceMap = getSourceMap filename, line, column
answer = sourceMap.sourceLocation [line - 1, column - 1] if sourceMap?
if answer? then [answer[0] + 1, answer[1] + 1] else null
frames = for frame in stack
break if frame.getFunction() is exports.run
" at #{formatSourcePosition frame, getSourceMapping}"
# Based on [michaelficarra/CoffeeScriptRedux](http://goo.gl/ZTx1p)
# NodeJS / V8 have no support for transforming positions in stack traces using
# sourceMap, so we must monkey-patch Error to display CoffeeScript source
# positions.
Error.prepareStackTrace = (err, stack) ->
frames = for frame in stack
# Dont display stack frames deeper than `CoffeeScript.run`.
break if frame.getFunction() is exports.run
" at #{formatSourcePosition frame, getSourceMapping}"
"#{err.toString()}\n#{frames.join '\n'}\n"
"#{err.toString()}\n#{frames.join '\n'}\n"
checkShebangLine = (file, input) ->
firstLine = input.split(/$/m)[0]

View File

@@ -32,12 +32,14 @@ BANNER = '''
# The list of all the valid option flags that `coffee` knows how to handle.
SWITCHES = [
[ '--ast', 'generate an abstract syntax tree of nodes']
['-b', '--bare', 'compile without a top-level function wrapper']
['-c', '--compile', 'compile to JavaScript and save as .js files']
['-e', '--eval', 'pass a string from the command line as input']
['-h', '--help', 'display this help message']
['-i', '--interactive', 'run an interactive CoffeeScript REPL']
['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling']
['-l', '--literate', 'treat stdio as literate style coffeescript']
['-m', '--map', 'generate source map and save as .js.map files']
['-M', '--inline-map', 'generate source map and include it directly in output']
['-n', '--nodes', 'print out the parse tree that the parser produces']
@@ -47,7 +49,6 @@ SWITCHES = [
['-p', '--print', 'print out the compiled JavaScript']
['-r', '--require [MODULE*]', 'require the given module before eval or REPL']
['-s', '--stdio', 'listen for and compile scripts over stdio']
['-l', '--literate', 'treat stdio as literate style coffeescript']
['-t', '--transpile', 'pipe generated JavaScript through Babel']
[ '--tokens', 'print out the tokens that the lexer/rewriter produce']
['-v', '--version', 'display the version number']
@@ -207,6 +208,9 @@ compileScript = (file, input, base = null) ->
printTokens CoffeeScript.tokens task.input, task.options
else if opts.nodes
printLine CoffeeScript.nodes(task.input, task.options).toString().trim()
else if opts.ast
compiled = CoffeeScript.compile task.input, task.options
printLine JSON.stringify(compiled, null, 2)
else if opts.run
CoffeeScript.register()
CoffeeScript.eval opts.prelude, task.options if opts.prelude
@@ -502,6 +506,7 @@ compileOptions = (filename, base) ->
transpile: opts.transpile
sourceMap: opts.map
inlineMap: opts['inline-map']
ast: opts.ast
if filename
if base
@@ -510,7 +515,7 @@ compileOptions = (filename, base) ->
jsDir = path.dirname jsPath
answer = helpers.merge answer, {
jsPath
sourceRoot: path.relative jsDir, cwd
sourceRoot: path.relative(jsDir, cwd) + path.sep
sourceFiles: [path.relative cwd, filename]
generatedFile: helpers.baseFileName(jsPath, no, useWinPathSep)
}

View File

@@ -34,6 +34,9 @@ o = (patternString, action, options) ->
patternString = patternString.replace /\s{2,}/g, ' '
patternCount = patternString.split(' ').length
if action
# This code block does string replacements in the generated `parser.js`
# file, replacing the calls to the `LOC` function and other strings as
# listed below.
action = if match = unwrap.exec action then match[1] else "(#{action}())"
# All runtime functions we need are defined on `yy`
@@ -44,12 +47,38 @@ o = (patternString, action, options) ->
# that nodes may have, such as comments or location data. Location data
# is added to the first parameter passed in, and the parameter is returned.
# If the parameter is not a node, it will just be passed through unaffected.
getAddDataToNodeFunctionString = (first, last) ->
"yy.addDataToNode(yy, @#{first}#{if last then ", @#{last}" else ''})"
getAddDataToNodeFunctionString = (first, last, forceUpdateLocation = yes) ->
"yy.addDataToNode(yy, @#{first}, #{if first[0] is '$' then '$$' else '$'}#{first}, #{if last then "@#{last}, #{if last[0] is '$' then '$$' else '$'}#{last}" else 'null, null'}, #{if forceUpdateLocation then 'true' else 'false'})"
# This code replaces the calls to `LOC` with the `yy.addDataToNode` string
# defined above. The `LOC` function, when used below in the grammar rules,
# is used to make sure that newly created node class objects get correct
# location data assigned to them. By default, the grammar will assign the
# location data spanned by *all* of the tokens on the left (e.g. a string
# such as `'Body TERMINATOR Line'`) to the “top-level” node returned by
# the grammar rule (the function on the right). But for “inner” node class
# objects created by grammar rules, they wont get correct location data
# assigned to them without adding `LOC`.
# For example, consider the grammar rule `'NEW_TARGET . Property'`, which
# is handled by a function that returns
# `new MetaProperty LOC(1)(new IdentifierLiteral $1), LOC(3)(new Access $3)`.
# The `1` in `LOC(1)` refers to the first token (`NEW_TARGET`) and the `3`
# in `LOC(3)` refers to the third token (`Property`). In order for the
# `new IdentifierLiteral` to get assigned the location data corresponding
# to `new` in the source code, we use
# `LOC(1)(new IdentifierLiteral ...)` to mean “assign the location data of
# the *first* token of this grammar rule (`NEW_TARGET`) to this
# `new IdentifierLiteral`”. The `LOC(3)` means “assign the location data of
# the *third* token of this grammar rule (`Property`) to this
# `new Access`”.
returnsLoc = /^LOC/.test action
action = action.replace /LOC\(([0-9]*)\)/g, getAddDataToNodeFunctionString('$1')
# A call to `LOC` with two arguments, e.g. `LOC(2,4)`, sets the location
# data for the generated node on both of the referenced tokens (the second
# and fourth in this example).
action = action.replace /LOC\(([0-9]*),\s*([0-9]*)\)/g, getAddDataToNodeFunctionString('$1', '$2')
performActionFunctionString = "$$ = #{getAddDataToNodeFunctionString(1, patternCount)}(#{action});"
performActionFunctionString = "$$ = #{getAddDataToNodeFunctionString(1, patternCount, not returnsLoc)}(#{action});"
else
performActionFunctionString = '$$ = $1;'
@@ -73,8 +102,8 @@ grammar =
# The **Root** is the top-level node in the syntax tree. Since we parse bottom-up,
# all parsing must end here.
Root: [
o '', -> new Block
o 'Body'
o '', -> new Root new Block
o 'Body', -> new Root $1
]
# Any list of statements and expressions, separated by line breaks or semicolons.
@@ -84,7 +113,7 @@ grammar =
o 'Body TERMINATOR'
]
# Block and statements, which make up a line in a body. YieldReturn is a
# Block and statements, which make up a line in a body. FuncDirective is a
# statement, but not included in Statement because that results in an ambiguous
# grammar.
Line: [
@@ -152,40 +181,68 @@ grammar =
Identifier: [
o 'IDENTIFIER', -> new IdentifierLiteral $1
o 'CSX_TAG', -> new CSXTag $1
o 'JSX_TAG', -> new JSXTag $1.toString(),
tagNameLocationData: $1.tagNameToken[2]
closingTagOpeningBracketLocationData: $1.closingTagOpeningBracketToken?[2]
closingTagSlashLocationData: $1.closingTagSlashToken?[2]
closingTagNameLocationData: $1.closingTagNameToken?[2]
closingTagClosingBracketLocationData: $1.closingTagClosingBracketToken?[2]
]
Property: [
o 'PROPERTY', -> new PropertyName $1
o 'PROPERTY', -> new PropertyName $1.toString()
]
# Alphanumerics are separated from the other **Literal** matchers because
# they can also serve as keys in object literals.
AlphaNumeric: [
o 'NUMBER', -> new NumberLiteral $1
o 'NUMBER', -> new NumberLiteral $1.toString(), parsedValue: $1.parsedValue
o 'String'
]
String: [
o 'STRING', -> new StringLiteral $1
o 'STRING_START Body STRING_END', -> new StringWithInterpolations $2
o 'STRING', ->
new StringLiteral(
$1.slice 1, -1 # strip artificial quotes and unwrap to primitive string
quote: $1.quote
initialChunk: $1.initialChunk
finalChunk: $1.finalChunk
indent: $1.indent
double: $1.double
heregex: $1.heregex
)
o 'STRING_START Interpolations STRING_END', -> new StringWithInterpolations Block.wrap($2), quote: $1.quote, startQuote: LOC(1)(new Literal $1.toString())
]
Interpolations: [
o 'InterpolationChunk', -> [$1]
o 'Interpolations InterpolationChunk', -> $1.concat $2
]
InterpolationChunk: [
o 'INTERPOLATION_START Body INTERPOLATION_END', -> new Interpolation $2
o 'INTERPOLATION_START INDENT Body OUTDENT INTERPOLATION_END', -> new Interpolation $3
o 'INTERPOLATION_START INTERPOLATION_END', -> new Interpolation
o 'String', -> $1
]
# The .toString() calls here and elsewhere are to convert `String` objects
# back to primitive strings now that we've retrieved stowaway extra properties
Regex: [
o 'REGEX', -> new RegexLiteral $1
o 'REGEX_START Invocation REGEX_END', -> new RegexWithInterpolations $2.args
o 'REGEX', -> new RegexLiteral $1.toString(), delimiter: $1.delimiter, heregexCommentTokens: $1.heregexCommentTokens
o 'REGEX_START Invocation REGEX_END', -> new RegexWithInterpolations $2, heregexCommentTokens: $3.heregexCommentTokens
]
# All of our immediate values. Generally these can be passed straight
# through and printed to JavaScript.
Literal: [
o 'AlphaNumeric'
o 'JS', -> new PassthroughLiteral $1
o 'JS', -> new PassthroughLiteral $1.toString(), here: $1.here, generated: $1.generated
o 'Regex'
o 'UNDEFINED', -> new UndefinedLiteral $1
o 'NULL', -> new NullLiteral $1
o 'BOOL', -> new BooleanLiteral $1
o 'INFINITY', -> new InfinityLiteral $1
o 'BOOL', -> new BooleanLiteral $1.toString(), originalValue: $1.original
o 'INFINITY', -> new InfinityLiteral $1.toString(), originalValue: $1.original
o 'NAN', -> new NaNLiteral $1
]
@@ -222,15 +279,16 @@ grammar =
ObjAssignable: [
o 'SimpleObjAssignable'
o '[ Expression ]', -> new Value new ComputedPropertyName $2
o '@ [ Expression ]', -> new Value LOC(1)(new ThisLiteral $1), [LOC(3)(new ComputedPropertyName($3))], 'this'
o 'AlphaNumeric'
]
# Object literal spread properties.
ObjRestValue: [
o 'SimpleObjAssignable ...', -> new Splat new Value $1
o '... SimpleObjAssignable', -> new Splat new Value $2
o '... SimpleObjAssignable', -> new Splat new Value($2), postfix: no
o 'ObjSpreadExpr ...', -> new Splat $1
o '... ObjSpreadExpr', -> new Splat $2
o '... ObjSpreadExpr', -> new Splat $2, postfix: no
]
ObjSpreadExpr: [
@@ -239,19 +297,15 @@ grammar =
o 'Parenthetical'
o 'Super'
o 'This'
o 'SUPER Arguments', -> new SuperCall LOC(1)(new Super), $2, no, $1
o 'SimpleObjAssignable Arguments', -> new Call (new Value $1), $2
o 'ObjSpreadExpr Arguments', -> new Call $1, $2
o 'SUPER OptFuncExist Arguments', -> new SuperCall LOC(1)(new Super), $3, $2.soak, $1
o 'DYNAMIC_IMPORT Arguments', -> new DynamicImportCall LOC(1)(new DynamicImport), $2
o 'SimpleObjAssignable OptFuncExist Arguments', -> new Call (new Value $1), $3, $2.soak
o 'ObjSpreadExpr OptFuncExist Arguments', -> new Call $1, $3, $2.soak
]
ObjSpreadIdentifier: [
o 'SimpleObjAssignable ObjSpreadAccessor', -> (new Value $1).add $2
o 'ObjSpreadExpr ObjSpreadAccessor', -> (new Value $1).add $2
]
ObjSpreadAccessor: [
o '. Property', -> new Access $2
o 'INDEX_START IndexValue INDEX_END', -> $2
o 'SimpleObjAssignable Accessor', -> (new Value $1).add $2
o 'ObjSpreadExpr Accessor', -> (new Value $1).add $2
]
# A return statement from a function body.
@@ -262,16 +316,16 @@ grammar =
]
YieldReturn: [
o 'YIELD RETURN Expression', -> new YieldReturn $3
o 'YIELD RETURN', -> new YieldReturn
o 'YIELD RETURN Expression', -> new YieldReturn $3, returnKeyword: LOC(2)(new Literal $2)
o 'YIELD RETURN', -> new YieldReturn null, returnKeyword: LOC(2)(new Literal $2)
]
AwaitReturn: [
o 'AWAIT RETURN Expression', -> new AwaitReturn $3
o 'AWAIT RETURN', -> new AwaitReturn
o 'AWAIT RETURN Expression', -> new AwaitReturn $3, returnKeyword: LOC(2)(new Literal $2)
o 'AWAIT RETURN', -> new AwaitReturn null, returnKeyword: LOC(2)(new Literal $2)
]
# The **Code** node is the function literal. It's defined by an indented block
# The **Code** node is the function literal. Its defined by an indented block
# of **Block** preceded by a function arrow, with an optional parameter list.
Code: [
o 'PARAM_START ParamList PARAM_END FuncGlyph Block', -> new Code $2, $5, $4, LOC(1)(new Literal $1)
@@ -312,7 +366,7 @@ grammar =
Param: [
o 'ParamVar', -> new Param $1
o 'ParamVar ...', -> new Param $1, null, on
o '... ParamVar', -> new Param $2, null, on
o '... ParamVar', -> new Param $2, null, postfix: no
o 'ParamVar = Expression', -> new Param $1, $3
o '...', -> new Expansion
]
@@ -328,7 +382,7 @@ grammar =
# A splat that occurs outside of a parameter list.
Splat: [
o 'Expression ...', -> new Splat $1
o '... Expression', -> new Splat $2
o '... Expression', -> new Splat $2, {postfix: no}
]
# Variables and properties that can be assigned to.
@@ -354,32 +408,43 @@ grammar =
o 'Parenthetical', -> new Value $1
o 'Range', -> new Value $1
o 'Invocation', -> new Value $1
o 'DoIife', -> new Value $1
o 'This'
o 'Super', -> new Value $1
o 'MetaProperty', -> new Value $1
]
# A `super`-based expression that can be used as a value.
Super: [
o 'SUPER . Property', -> new Super LOC(3)(new Access $3), [], no, $1
o 'SUPER INDEX_START Expression INDEX_END', -> new Super LOC(3)(new Index $3), [], no, $1
o 'SUPER . Property', -> new Super LOC(3)(new Access $3), LOC(1)(new Literal $1)
o 'SUPER INDEX_START Expression INDEX_END', -> new Super LOC(3)(new Index $3), LOC(1)(new Literal $1)
o 'SUPER INDEX_START INDENT Expression OUTDENT INDEX_END', -> new Super LOC(4)(new Index $4), LOC(1)(new Literal $1)
]
# A “meta-property” access e.g. `new.target` or `import.meta`, where
# something that looks like a property is referenced on a keyword.
MetaProperty: [
o 'NEW_TARGET . Property', -> new MetaProperty LOC(1)(new IdentifierLiteral $1), LOC(3)(new Access $3)
o 'IMPORT_META . Property', -> new MetaProperty LOC(1)(new IdentifierLiteral $1), LOC(3)(new Access $3)
]
# The general group of accessors into an object, by property, by prototype
# or by array index or slice.
Accessor: [
o '. Property', -> new Access $2
o '?. Property', -> new Access $2, 'soak'
o ':: Property', -> [LOC(1)(new Access new PropertyName('prototype')), LOC(2)(new Access $2)]
o '?:: Property', -> [LOC(1)(new Access new PropertyName('prototype'), 'soak'), LOC(2)(new Access $2)]
o '::', -> new Access new PropertyName 'prototype'
o '?::', -> new Access new PropertyName('prototype'), 'soak'
o '?. Property', -> new Access $2, soak: yes
o ':: Property', -> [LOC(1)(new Access new PropertyName('prototype'), shorthand: yes), LOC(2)(new Access $2)]
o '?:: Property', -> [LOC(1)(new Access new PropertyName('prototype'), shorthand: yes, soak: yes), LOC(2)(new Access $2)]
o '::', -> new Access new PropertyName('prototype'), shorthand: yes
o '?::', -> new Access new PropertyName('prototype'), shorthand: yes, soak: yes
o 'Index'
]
# Indexing into an object or array using bracket notation.
Index: [
o 'INDEX_START IndexValue INDEX_END', -> $2
o 'INDEX_SOAK Index', -> extend $2, soak: yes
o 'INDEX_START IndexValue INDEX_END', -> $2
o 'INDEX_START INDENT IndexValue OUTDENT INDEX_END', -> $3
o 'INDEX_SOAK Index', -> extend $2, soak: yes
]
IndexValue: [
@@ -416,13 +481,20 @@ grammar =
]
Import: [
o 'IMPORT String', -> new ImportDeclaration null, $2
o 'IMPORT ImportDefaultSpecifier FROM String', -> new ImportDeclaration new ImportClause($2, null), $4
o 'IMPORT ImportNamespaceSpecifier FROM String', -> new ImportDeclaration new ImportClause(null, $2), $4
o 'IMPORT { } FROM String', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList []), $5
o 'IMPORT { ImportSpecifierList OptComma } FROM String', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList $3), $7
o 'IMPORT ImportDefaultSpecifier , ImportNamespaceSpecifier FROM String', -> new ImportDeclaration new ImportClause($2, $4), $6
o 'IMPORT ImportDefaultSpecifier , { ImportSpecifierList OptComma } FROM String', -> new ImportDeclaration new ImportClause($2, new ImportSpecifierList $5), $9
o 'IMPORT String', -> new ImportDeclaration null, $2
o 'IMPORT String ASSERT Object', -> new ImportDeclaration null, $2, $4
o 'IMPORT ImportDefaultSpecifier FROM String', -> new ImportDeclaration new ImportClause($2, null), $4
o 'IMPORT ImportDefaultSpecifier FROM String ASSERT Object', -> new ImportDeclaration new ImportClause($2, null), $4, $6
o 'IMPORT ImportNamespaceSpecifier FROM String', -> new ImportDeclaration new ImportClause(null, $2), $4
o 'IMPORT ImportNamespaceSpecifier FROM String ASSERT Object', -> new ImportDeclaration new ImportClause(null, $2), $4, $6
o 'IMPORT { } FROM String', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList []), $5
o 'IMPORT { } FROM String ASSERT Object', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList []), $5, $7
o 'IMPORT { ImportSpecifierList OptComma } FROM String', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList $3), $7
o 'IMPORT { ImportSpecifierList OptComma } FROM String ASSERT Object', -> new ImportDeclaration new ImportClause(null, new ImportSpecifierList $3), $7, $9
o 'IMPORT ImportDefaultSpecifier , ImportNamespaceSpecifier FROM String', -> new ImportDeclaration new ImportClause($2, $4), $6
o 'IMPORT ImportDefaultSpecifier , ImportNamespaceSpecifier FROM String ASSERT Object', -> new ImportDeclaration new ImportClause($2, $4), $6, $8
o 'IMPORT ImportDefaultSpecifier , { ImportSpecifierList OptComma } FROM String', -> new ImportDeclaration new ImportClause($2, new ImportSpecifierList $5), $9
o 'IMPORT ImportDefaultSpecifier , { ImportSpecifierList OptComma } FROM String ASSERT Object', -> new ImportDeclaration new ImportClause($2, new ImportSpecifierList $5), $9, $11
]
ImportSpecifierList: [
@@ -436,8 +508,8 @@ grammar =
ImportSpecifier: [
o 'Identifier', -> new ImportSpecifier $1
o 'Identifier AS Identifier', -> new ImportSpecifier $1, $3
o 'DEFAULT', -> new ImportSpecifier new Literal $1
o 'DEFAULT AS Identifier', -> new ImportSpecifier new Literal($1), $3
o 'DEFAULT', -> new ImportSpecifier LOC(1)(new DefaultLiteral $1)
o 'DEFAULT AS Identifier', -> new ImportSpecifier LOC(1)(new DefaultLiteral($1)), $3
]
ImportDefaultSpecifier: [
@@ -449,19 +521,23 @@ grammar =
]
Export: [
o 'EXPORT { }', -> new ExportNamedDeclaration new ExportSpecifierList []
o 'EXPORT { ExportSpecifierList OptComma }', -> new ExportNamedDeclaration new ExportSpecifierList $3
o 'EXPORT Class', -> new ExportNamedDeclaration $2
o 'EXPORT Identifier = Expression', -> new ExportNamedDeclaration new Assign $2, $4, null,
moduleDeclaration: 'export'
o 'EXPORT Identifier = TERMINATOR Expression', -> new ExportNamedDeclaration new Assign $2, $5, null,
moduleDeclaration: 'export'
o 'EXPORT Identifier = INDENT Expression OUTDENT', -> new ExportNamedDeclaration new Assign $2, $5, null,
moduleDeclaration: 'export'
o 'EXPORT DEFAULT Expression', -> new ExportDefaultDeclaration $3
o 'EXPORT DEFAULT INDENT Object OUTDENT', -> new ExportDefaultDeclaration new Value $4
o 'EXPORT EXPORT_ALL FROM String', -> new ExportAllDeclaration new Literal($2), $4
o 'EXPORT { ExportSpecifierList OptComma } FROM String', -> new ExportNamedDeclaration new ExportSpecifierList($3), $7
o 'EXPORT { }', -> new ExportNamedDeclaration new ExportSpecifierList []
o 'EXPORT { ExportSpecifierList OptComma }', -> new ExportNamedDeclaration new ExportSpecifierList $3
o 'EXPORT Class', -> new ExportNamedDeclaration $2
o 'EXPORT Identifier = Expression', -> new ExportNamedDeclaration LOC(2,4)(new Assign $2, $4, null,
moduleDeclaration: 'export')
o 'EXPORT Identifier = TERMINATOR Expression', -> new ExportNamedDeclaration LOC(2,5)(new Assign $2, $5, null,
moduleDeclaration: 'export')
o 'EXPORT Identifier = INDENT Expression OUTDENT', -> new ExportNamedDeclaration LOC(2,6)(new Assign $2, $5, null,
moduleDeclaration: 'export')
o 'EXPORT DEFAULT Expression', -> new ExportDefaultDeclaration $3
o 'EXPORT DEFAULT INDENT Object OUTDENT', -> new ExportDefaultDeclaration new Value $4
o 'EXPORT EXPORT_ALL FROM String', -> new ExportAllDeclaration new Literal($2), $4
o 'EXPORT EXPORT_ALL FROM String ASSERT Object', -> new ExportAllDeclaration new Literal($2), $4, $6
o 'EXPORT { } FROM String', -> new ExportNamedDeclaration new ExportSpecifierList([]), $5
o 'EXPORT { } FROM String ASSERT Object', -> new ExportNamedDeclaration new ExportSpecifierList([]), $5, $7
o 'EXPORT { ExportSpecifierList OptComma } FROM String', -> new ExportNamedDeclaration new ExportSpecifierList($3), $7
o 'EXPORT { ExportSpecifierList OptComma } FROM String ASSERT Object', -> new ExportNamedDeclaration new ExportSpecifierList($3), $7, $9
]
ExportSpecifierList: [
@@ -475,28 +551,29 @@ grammar =
ExportSpecifier: [
o 'Identifier', -> new ExportSpecifier $1
o 'Identifier AS Identifier', -> new ExportSpecifier $1, $3
o 'Identifier AS DEFAULT', -> new ExportSpecifier $1, new Literal $3
o 'DEFAULT', -> new ExportSpecifier new Literal $1
o 'DEFAULT AS Identifier', -> new ExportSpecifier new Literal($1), $3
o 'Identifier AS DEFAULT', -> new ExportSpecifier $1, LOC(3)(new DefaultLiteral $3)
o 'DEFAULT', -> new ExportSpecifier LOC(1)(new DefaultLiteral $1)
o 'DEFAULT AS Identifier', -> new ExportSpecifier LOC(1)(new DefaultLiteral($1)), $3
]
# Ordinary function invocation, or a chained series of calls.
Invocation: [
o 'Value OptFuncExist String', -> new TaggedTemplateCall $1, $3, $2
o 'Value OptFuncExist Arguments', -> new Call $1, $3, $2
o 'SUPER OptFuncExist Arguments', -> new SuperCall LOC(1)(new Super), $3, $2, $1
o 'Value OptFuncExist String', -> new TaggedTemplateCall $1, $3, $2.soak
o 'Value OptFuncExist Arguments', -> new Call $1, $3, $2.soak
o 'SUPER OptFuncExist Arguments', -> new SuperCall LOC(1)(new Super), $3, $2.soak, $1
o 'DYNAMIC_IMPORT Arguments', -> new DynamicImportCall LOC(1)(new DynamicImport), $2
]
# An optional existence check on a function.
OptFuncExist: [
o '', -> no
o 'FUNC_EXIST', -> yes
o '', -> soak: no
o 'FUNC_EXIST', -> soak: yes
]
# The list of arguments to a function call.
Arguments: [
o 'CALL_START CALL_END', -> []
o 'CALL_START ArgList OptComma CALL_END', -> $2
o 'CALL_START ArgList OptComma CALL_END', -> $2.implicit = $1.generated; $2
]
# A reference to the *this* current object.
@@ -519,24 +596,24 @@ grammar =
# Inclusive and exclusive range dots.
RangeDots: [
o '..', -> 'inclusive'
o '...', -> 'exclusive'
o '..', -> exclusive: no
o '...', -> exclusive: yes
]
# The CoffeeScript range literal.
Range: [
o '[ Expression RangeDots Expression ]', -> new Range $2, $4, $3
o '[ ExpressionLine RangeDots Expression ]', -> new Range $2, $4, $3
o '[ Expression RangeDots Expression ]', -> new Range $2, $4, if $3.exclusive then 'exclusive' else 'inclusive'
o '[ ExpressionLine RangeDots Expression ]', -> new Range $2, $4, if $3.exclusive then 'exclusive' else 'inclusive'
]
# Array slice literals.
Slice: [
o 'Expression RangeDots Expression', -> new Range $1, $3, $2
o 'Expression RangeDots', -> new Range $1, null, $2
o 'ExpressionLine RangeDots Expression', -> new Range $1, $3, $2
o 'ExpressionLine RangeDots', -> new Range $1, null, $2
o 'RangeDots Expression', -> new Range null, $2, $1
o 'RangeDots', -> new Range null, null, $1
o 'Expression RangeDots Expression', -> new Range $1, $3, if $2.exclusive then 'exclusive' else 'inclusive'
o 'Expression RangeDots', -> new Range $1, null, if $2.exclusive then 'exclusive' else 'inclusive'
o 'ExpressionLine RangeDots Expression', -> new Range $1, $3, if $2.exclusive then 'exclusive' else 'inclusive'
o 'ExpressionLine RangeDots', -> new Range $1, null, if $2.exclusive then 'exclusive' else 'inclusive'
o 'RangeDots Expression', -> new Range null, $2, if $1.exclusive then 'exclusive' else 'inclusive'
o 'RangeDots', -> new Range null, null, if $1.exclusive then 'exclusive' else 'inclusive'
]
# The **ArgList** is the list of objects passed into a function call
@@ -562,7 +639,7 @@ grammar =
ArgElisionList: [
o 'ArgElision'
o 'ArgElisionList , ArgElision', -> $1.concat $3
o 'ArgElisionList OptElisions TERMINATOR ArgElision', -> $1.concat $2, $4
o 'ArgElisionList OptComma TERMINATOR ArgElision', -> $1.concat $4
o 'INDENT ArgElisionList OptElisions OUTDENT', -> $2.concat $3
o 'ArgElisionList OptElisions INDENT ArgElisionList OptElisions OUTDENT', -> $1.concat $2, $4, $5
]
@@ -584,6 +661,7 @@ grammar =
Elision: [
o ',', -> new Elision
o 'Elision TERMINATOR', -> $1
]
# Just simple, comma-separated, required arguments (no fancy syntax). We need
@@ -599,16 +677,16 @@ grammar =
# The variants of *try/catch/finally* exception handling blocks.
Try: [
o 'TRY Block', -> new Try $2
o 'TRY Block Catch', -> new Try $2, $3[0], $3[1]
o 'TRY Block FINALLY Block', -> new Try $2, null, null, $4
o 'TRY Block Catch FINALLY Block', -> new Try $2, $3[0], $3[1], $5
o 'TRY Block Catch', -> new Try $2, $3
o 'TRY Block FINALLY Block', -> new Try $2, null, $4, LOC(3)(new Literal $3)
o 'TRY Block Catch FINALLY Block', -> new Try $2, $3, $5, LOC(4)(new Literal $4)
]
# A catch clause names its error and runs a block of code.
Catch: [
o 'CATCH Identifier Block', -> [$2, $3]
o 'CATCH Object Block', -> [LOC(2)(new Value($2)), $3]
o 'CATCH Block', -> [null, $2]
o 'CATCH Identifier Block', -> new Catch $3, $2
o 'CATCH Object Block', -> new Catch $3, LOC(2)(new Value($2))
o 'CATCH Block', -> new Catch $2
]
# Throw an exception object.
@@ -648,22 +726,22 @@ grammar =
While: [
o 'WhileSource Block', -> $1.addBody $2
o 'WhileLineSource Block', -> $1.addBody $2
o 'Statement WhileSource', -> $2.addBody LOC(1) Block.wrap([$1])
o 'Expression WhileSource', -> $2.addBody LOC(1) Block.wrap([$1])
o 'Statement WhileSource', -> (Object.assign $2, postfix: yes).addBody LOC(1) Block.wrap([$1])
o 'Expression WhileSource', -> (Object.assign $2, postfix: yes).addBody LOC(1) Block.wrap([$1])
o 'Loop', -> $1
]
Loop: [
o 'LOOP Block', -> new While(LOC(1) new BooleanLiteral 'true').addBody $2
o 'LOOP Expression', -> new While(LOC(1) new BooleanLiteral 'true').addBody LOC(2) Block.wrap [$2]
o 'LOOP Block', -> new While(LOC(1)(new BooleanLiteral 'true'), isLoop: yes).addBody $2
o 'LOOP Expression', -> new While(LOC(1)(new BooleanLiteral 'true'), isLoop: yes).addBody LOC(2) Block.wrap [$2]
]
# Array, object, and range comprehensions, at the most generic level.
# Comprehensions can either be normal, with a block of expressions to execute,
# or postfix, with a single expression.
For: [
o 'Statement ForBody', -> $2.addBody $1
o 'Expression ForBody', -> $2.addBody $1
o 'Statement ForBody', -> $2.postfix = yes; $2.addBody $1
o 'Expression ForBody', -> $2.postfix = yes; $2.addBody $1
o 'ForBody Block', -> $1.addBody $2
o 'ForLineBody Block', -> $1.addBody $2
]
@@ -707,7 +785,7 @@ grammar =
]
# The source of a comprehension is an array or object with an optional guard
# clause. If it's an array comprehension, you can also choose to step through
# clause. If its an array comprehension, you can also choose to step through
# in fixed-size increments.
ForSource: [
o 'FORIN Expression', -> source: $2
@@ -756,21 +834,21 @@ grammar =
Switch: [
o 'SWITCH Expression INDENT Whens OUTDENT', -> new Switch $2, $4
o 'SWITCH ExpressionLine INDENT Whens OUTDENT', -> new Switch $2, $4
o 'SWITCH Expression INDENT Whens ELSE Block OUTDENT', -> new Switch $2, $4, $6
o 'SWITCH ExpressionLine INDENT Whens ELSE Block OUTDENT', -> new Switch $2, $4, $6
o 'SWITCH Expression INDENT Whens ELSE Block OUTDENT', -> new Switch $2, $4, LOC(5,6) $6
o 'SWITCH ExpressionLine INDENT Whens ELSE Block OUTDENT', -> new Switch $2, $4, LOC(5,6) $6
o 'SWITCH INDENT Whens OUTDENT', -> new Switch null, $3
o 'SWITCH INDENT Whens ELSE Block OUTDENT', -> new Switch null, $3, $5
o 'SWITCH INDENT Whens ELSE Block OUTDENT', -> new Switch null, $3, LOC(4,5) $5
]
Whens: [
o 'When'
o 'When', -> [$1]
o 'Whens When', -> $1.concat $2
]
# An individual **When** clause, with action.
When: [
o 'LEADING_WHEN SimpleArgs Block', -> [[$2, $3]]
o 'LEADING_WHEN SimpleArgs Block TERMINATOR', -> [[$2, $3]]
o 'LEADING_WHEN SimpleArgs Block', -> new SwitchWhen $2, $3
o 'LEADING_WHEN SimpleArgs Block TERMINATOR', -> LOC(1, 3) new SwitchWhen $2, $3
]
# The most basic form of *if* is a condition and an action. The following
@@ -786,8 +864,8 @@ grammar =
If: [
o 'IfBlock'
o 'IfBlock ELSE Block', -> $1.addElse $3
o 'Statement POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
o 'Expression POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
o 'Statement POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
o 'Expression POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
]
IfBlockLine: [
@@ -798,8 +876,8 @@ grammar =
IfLine: [
o 'IfBlockLine'
o 'IfBlockLine ELSE Block', -> $1.addElse $3
o 'Statement POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
o 'Expression POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
o 'Statement POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
o 'Expression POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
]
# Arithmetic and logical operators, working on one or more operands.
@@ -810,11 +888,14 @@ grammar =
# rules are necessary.
OperationLine: [
o 'UNARY ExpressionLine', -> new Op $1, $2
o 'DO ExpressionLine', -> new Op $1, $2
o 'DO_IIFE CodeLine', -> new Op $1, $2
]
Operation: [
o 'UNARY Expression', -> new Op $1 , $2
o 'UNARY_MATH Expression', -> new Op $1 , $2
o 'UNARY Expression', -> new Op $1.toString(), $2, undefined, undefined, originalOperator: $1.original
o 'DO Expression', -> new Op $1, $2
o 'UNARY_MATH Expression', -> new Op $1, $2
o '- Expression', (-> new Op '-', $2), prec: 'UNARY_MATH'
o '+ Expression', (-> new Op '+', $2), prec: 'UNARY_MATH'
@@ -835,25 +916,25 @@ grammar =
o 'Expression MATH Expression', -> new Op $2, $1, $3
o 'Expression ** Expression', -> new Op $2, $1, $3
o 'Expression SHIFT Expression', -> new Op $2, $1, $3
o 'Expression COMPARE Expression', -> new Op $2, $1, $3
o 'Expression COMPARE Expression', -> new Op $2.toString(), $1, $3, undefined, originalOperator: $2.original
o 'Expression & Expression', -> new Op $2, $1, $3
o 'Expression ^ Expression', -> new Op $2, $1, $3
o 'Expression | Expression', -> new Op $2, $1, $3
o 'Expression && Expression', -> new Op $2, $1, $3
o 'Expression || Expression', -> new Op $2, $1, $3
o 'Expression && Expression', -> new Op $2.toString(), $1, $3, undefined, originalOperator: $2.original
o 'Expression || Expression', -> new Op $2.toString(), $1, $3, undefined, originalOperator: $2.original
o 'Expression BIN? Expression', -> new Op $2, $1, $3
o 'Expression RELATION Expression', ->
if $2.charAt(0) is '!'
new Op($2[1..], $1, $3).invert()
else
new Op $2, $1, $3
o 'Expression RELATION Expression', -> new Op $2.toString(), $1, $3, undefined, invertOperator: $2.invert?.original ? $2.invert
o 'SimpleAssignable COMPOUND_ASSIGN
Expression', -> new Assign $1, $3, $2
Expression', -> new Assign $1, $3, $2.toString(), originalContext: $2.original
o 'SimpleAssignable COMPOUND_ASSIGN
INDENT Expression OUTDENT', -> new Assign $1, $4, $2
INDENT Expression OUTDENT', -> new Assign $1, $4, $2.toString(), originalContext: $2.original
o 'SimpleAssignable COMPOUND_ASSIGN TERMINATOR
Expression', -> new Assign $1, $4, $2
Expression', -> new Assign $1, $4, $2.toString(), originalContext: $2.original
]
DoIife: [
o 'DO_IIFE Code', -> new Op $1 , $2
]
# Precedence
@@ -868,11 +949,12 @@ grammar =
#
# (2 + 3) * 4
operators = [
['right', 'DO_IIFE']
['left', '.', '?.', '::', '?::']
['left', 'CALL_START', 'CALL_END']
['nonassoc', '++', '--']
['left', '?']
['right', 'UNARY']
['right', 'UNARY', 'DO']
['right', 'AWAIT']
['right', '**']
['right', 'UNARY_MATH']
@@ -891,7 +973,7 @@ operators = [
['right', 'YIELD']
['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS']
['right', 'FORIN', 'FOROF', 'FORFROM', 'BY', 'WHEN']
['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT']
['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'IMPORT', 'EXPORT', 'DYNAMIC_IMPORT']
['left', 'POST_IF']
]

View File

@@ -107,15 +107,36 @@ buildLocationData = (first, last) ->
first_column: first.first_column
last_line: last.last_line
last_column: last.last_column
last_line_exclusive: last.last_line_exclusive
last_column_exclusive: last.last_column_exclusive
range: [
first.range[0]
last.range[1]
]
# Build a list of all comments attached to tokens.
exports.extractAllCommentTokens = (tokens) ->
allCommentsObj = {}
for token in tokens when token.comments
for comment in token.comments
commentKey = comment.locationData.range[0]
allCommentsObj[commentKey] = comment
sortedKeys = Object.keys(allCommentsObj).sort (a, b) -> a - b
for key in sortedKeys
allCommentsObj[key]
# Get a lookup hash for a token based on its location data.
# Multiple tokens might have the same location hash, but using exclusive
# location data distinguishes e.g. zero-length generated tokens from
# actual source tokens.
buildLocationHash = (loc) ->
"#{loc.first_line}x#{loc.first_column}-#{loc.last_line}x#{loc.last_column}"
"#{loc.range[0]}-#{loc.range[1]}"
# Build a dictionary of extra token properties organized by tokens locations
# used as lookup hashes.
buildTokenDataDictionary = (parserState) ->
exports.buildTokenDataDictionary = buildTokenDataDictionary = (tokens) ->
tokenData = {}
for token in parserState.parser.tokens when token.comments
for token in tokens when token.comments
tokenHash = buildLocationHash token[2]
# Multiple tokens might have the same location hash, such as the generated
# `JS` tokens added at the start or end of the token stream to hold
@@ -132,15 +153,18 @@ buildTokenDataDictionary = (parserState) ->
# This returns a function which takes an object as a parameter, and if that
# object is an AST node, updates that object's locationData.
# The object is returned either way.
exports.addDataToNode = (parserState, first, last) ->
exports.addDataToNode = (parserState, firstLocationData, firstValue, lastLocationData, lastValue, forceUpdateLocation = yes) ->
(obj) ->
# Add location data.
if obj?.updateLocationDataIfMissing? and first?
obj.updateLocationDataIfMissing buildLocationData(first, last)
locationData = buildLocationData(firstValue?.locationData ? firstLocationData, lastValue?.locationData ? lastLocationData)
if obj?.updateLocationDataIfMissing? and firstLocationData?
obj.updateLocationDataIfMissing locationData, forceUpdateLocation
else
obj.locationData = locationData
# Add comments, building the dictionary of token data if it hasnt been
# built yet.
parserState.tokenData ?= buildTokenDataDictionary parserState
parserState.tokenData ?= buildTokenDataDictionary parserState.parser.tokens
if obj.locationData?
objHash = buildLocationHash obj.locationData
if parserState.tokenData[objHash]?.comments?
@@ -164,6 +188,13 @@ exports.locationDataToString = (obj) ->
else
"No location data"
# Generate a unique anonymous file name so we can distinguish source map cache
# entries for any number of anonymous scripts.
exports.anonymousFileName = do ->
n = 0
->
"<anonymous-#{n++}>"
# A `.coffee.md` compatible version of `basename`, that returns the file sans-extension.
exports.baseFileName = (file, stripExt = no, useWinPathSep = no) ->
pathSep = if useWinPathSep then /\\|\// else /\//
@@ -214,7 +245,11 @@ syntaxErrorToString = ->
last_line ?= first_line
last_column ?= first_column
filename = @filename or '[stdin]'
if @filename?.startsWith '<anonymous'
filename = '[stdin]'
else
filename = @filename or '[stdin]'
codeLine = @code.split('\n')[first_line]
start = first_column
# Show only the first line on multi-line errors.
@@ -243,3 +278,54 @@ exports.nameWhitespaceCharacter = (string) ->
when '\r' then 'carriage return'
when '\t' then 'tab'
else string
exports.parseNumber = (string) ->
return NaN unless string?
base = switch string.charAt 1
when 'b' then 2
when 'o' then 8
when 'x' then 16
else null
if base?
parseInt string[2..].replace(/_/g, ''), base
else
parseFloat string.replace(/_/g, '')
exports.isFunction = (obj) -> Object::toString.call(obj) is '[object Function]'
exports.isNumber = isNumber = (obj) -> Object::toString.call(obj) is '[object Number]'
exports.isString = isString = (obj) -> Object::toString.call(obj) is '[object String]'
exports.isBoolean = isBoolean = (obj) -> obj is yes or obj is no or Object::toString.call(obj) is '[object Boolean]'
exports.isPlainObject = (obj) -> typeof obj is 'object' and !!obj and not Array.isArray(obj) and not isNumber(obj) and not isString(obj) and not isBoolean(obj)
unicodeCodePointToUnicodeEscapes = (codePoint) ->
toUnicodeEscape = (val) ->
str = val.toString 16
"\\u#{repeat '0', 4 - str.length}#{str}"
return toUnicodeEscape(codePoint) if codePoint < 0x10000
# surrogate pair
high = Math.floor((codePoint - 0x10000) / 0x400) + 0xD800
low = (codePoint - 0x10000) % 0x400 + 0xDC00
"#{toUnicodeEscape(high)}#{toUnicodeEscape(low)}"
# Replace `\u{...}` with `\uxxxx[\uxxxx]` in regexes without `u` flag
exports.replaceUnicodeCodePointEscapes = (str, {flags, error, delimiter = ''} = {}) ->
shouldReplace = flags? and 'u' not in flags
str.replace UNICODE_CODE_POINT_ESCAPE, (match, escapedBackslash, codePointHex, offset) ->
return escapedBackslash if escapedBackslash
codePointDecimal = parseInt codePointHex, 16
if codePointDecimal > 0x10ffff
error "unicode code point escapes greater than \\u{10ffff} are not allowed",
offset: offset + delimiter.length
length: codePointHex.length + 4
return match unless shouldReplace
unicodeCodePointToUnicodeEscapes codePointDecimal
UNICODE_CODE_POINT_ESCAPE = ///
( \\\\ ) # Make sure the escape isnt escaped.
|
\\u\{ ( [\da-fA-F]+ ) \}
///g

View File

@@ -37,7 +37,7 @@ CoffeeScript.run = (code, options = {}) ->
# Set the filename.
mainModule.filename = process.argv[1] =
if options.filename then fs.realpathSync(options.filename) else '<anonymous>'
if options.filename then fs.realpathSync(options.filename) else helpers.anonymousFileName()
# Clear the module cache.
mainModule.moduleCache and= {}
@@ -52,10 +52,12 @@ CoffeeScript.run = (code, options = {}) ->
# Save the options for compiling child imports.
mainModule.options = options
options.filename = mainModule.filename
options.inlineMap = true
# Compile.
if not helpers.isCoffee(mainModule.filename) or require.extensions
answer = CoffeeScript.compile code, options
code = answer.js ? answer
answer = CoffeeScript.compile code, options
code = answer.js ? answer
mainModule._compile code, mainModule.filename
@@ -110,8 +112,8 @@ if require.extensions
Use CoffeeScript.register() or require the coffeescript/register module to require #{ext} files.
"""
CoffeeScript._compileFile = (filename, options = {}) ->
raw = fs.readFileSync filename, 'utf8'
CoffeeScript._compileRawFileContent = (raw, filename, options = {}) ->
# Strip the Unicode byte order mark, if this file begins with one.
stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw
@@ -119,7 +121,6 @@ CoffeeScript._compileFile = (filename, options = {}) ->
filename: filename
literate: helpers.isLiterate filename
sourceFiles: [filename]
inlineMap: yes # Always generate a source map, so that stack traces line up.
try
answer = CoffeeScript.compile stripped, options
@@ -131,4 +132,29 @@ CoffeeScript._compileFile = (filename, options = {}) ->
answer
CoffeeScript._compileFile = (filename, options = {}) ->
raw = fs.readFileSync filename, 'utf8'
CoffeeScript._compileRawFileContent raw, filename, options
module.exports = CoffeeScript
# Explicitly define all named exports so that Nodes automatic detection of
# named exports from CommonJS packages finds all of them. This enables consuming
# packages to write code like `import { compile } from 'coffeescript'`.
# Dont simplify this into a loop or similar; the `module.exports.name` part is
# essential for Nodes algorithm to successfully detect the name.
module.exports.VERSION = CoffeeScript.VERSION
module.exports.FILE_EXTENSIONS = CoffeeScript.FILE_EXTENSIONS
module.exports.helpers = CoffeeScript.helpers
module.exports.registerCompiled = CoffeeScript.registerCompiled
module.exports.compile = CoffeeScript.compile
module.exports.tokens = CoffeeScript.tokens
module.exports.nodes = CoffeeScript.nodes
module.exports.register = CoffeeScript.register
module.exports.eval = CoffeeScript.eval
module.exports.run = CoffeeScript.run
module.exports.transpile = CoffeeScript.transpile
module.exports.patchStackTrace = CoffeeScript.patchStackTrace
module.exports._compileRawFileContent = CoffeeScript._compileRawFileContent
module.exports._compileFile = CoffeeScript._compileFile

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,11 +3,29 @@ child_process = require 'child_process'
helpers = require './helpers'
path = require 'path'
{patchStackTrace} = CoffeeScript
# Check if Node's built-in source map stack trace transformations are enabled.
nodeSourceMapsSupportEnabled = process? and (
process.execArgv.includes('--enable-source-maps') or
process.env.NODE_OPTIONS?.includes('--enable-source-maps')
)
unless Error.prepareStackTrace or nodeSourceMapsSupportEnabled
cacheSourceMaps = true
patchStackTrace()
# Load and run a CoffeeScript file for Node, stripping any `BOM`s.
loadFile = (module, filename) ->
options = module.options or getRootModule(module).options
answer = CoffeeScript._compileFile filename, options
module._compile answer, filename
options = module.options or getRootModule(module).options or {}
# Currently `CoffeeScript.compile` caches all source maps if present. They
# are available in `getSourceMap` retrieved by `filename`.
if cacheSourceMaps or nodeSourceMapsSupportEnabled
options.inlineMap = true
js = CoffeeScript._compileFile filename, options
module._compile js, filename
# If the installed version of Node supports `require.extensions`, register
# CoffeeScript as an extension.

View File

@@ -25,30 +25,30 @@ replDefaults =
input = input.replace /^\s*try\s*{([\s\S]*)}\s*catch.*$/m, '$1'
# Require AST nodes to do some AST manipulation.
{Block, Assign, Value, Literal, Call, Code} = require './nodes'
{Block, Assign, Value, Literal, Call, Code, Root} = require './nodes'
try
# Tokenize the clean input.
tokens = CoffeeScript.tokens input
# Filter out tokens generated just to hold comments.
if tokens.length >= 2 and tokens[0].generated and
tokens[0].comments?.length isnt 0 and tokens[0][1] is '' and
tokens[0].comments?.length isnt 0 and "#{tokens[0][1]}" is '' and
tokens[1][0] is 'TERMINATOR'
tokens = tokens[2...]
if tokens.length >= 1 and tokens[tokens.length - 1].generated and
tokens[tokens.length - 1].comments?.length isnt 0 and tokens[tokens.length - 1][1] is ''
tokens[tokens.length - 1].comments?.length isnt 0 and "#{tokens[tokens.length - 1][1]}" is ''
tokens.pop()
# Collect referenced variable names just like in `CoffeeScript.compile`.
referencedVars = (token[1] for token in tokens when token[0] is 'IDENTIFIER')
# Generate the AST of the tokens.
ast = CoffeeScript.nodes tokens
ast = CoffeeScript.nodes(tokens).body
# Add assignment to `__` variable to force the input to be an expression.
ast = new Block [new Assign (new Value new Literal '__'), ast, '=']
# Wrap the expression in a closure to support top-level `await`.
ast = new Code [], ast
isAsync = ast.isAsync
# Invoke the wrapping closure.
ast = new Block [new Call ast]
ast = new Root new Block [new Call ast]
js = ast.compile {bare: yes, locals: Object.keys(context), referencedVars, sharedScope: yes}
if transpile
js = transpile.transpile(js, transpile.options).code
@@ -75,7 +75,7 @@ runInContext = (js, context, filename) ->
vm.runInContext js, context, filename
addMultilineHandler = (repl) ->
{rli, inputStream, outputStream} = repl
{inputStream, outputStream} = repl
# Node 0.11.12 changed API, prompt is now _prompt.
origPrompt = repl._prompt ? repl.prompt
@@ -86,15 +86,15 @@ addMultilineHandler = (repl) ->
buffer: ''
# Proxy node's line listener
nodeLineListener = rli.listeners('line')[0]
rli.removeListener 'line', nodeLineListener
rli.on 'line', (cmd) ->
nodeLineListener = repl.listeners('line')[0]
repl.removeListener 'line', nodeLineListener
repl.on 'line', (cmd) ->
if multiline.enabled
multiline.buffer += "#{cmd}\n"
rli.setPrompt multiline.prompt
rli.prompt true
repl.setPrompt multiline.prompt
repl.prompt true
else
rli.setPrompt origPrompt
repl.setPrompt origPrompt
nodeLineListener cmd
return
@@ -105,25 +105,25 @@ addMultilineHandler = (repl) ->
# allow arbitrarily switching between modes any time before multiple lines are entered
unless multiline.buffer.match /\n/
multiline.enabled = not multiline.enabled
rli.setPrompt origPrompt
rli.prompt true
repl.setPrompt origPrompt
repl.prompt true
return
# no-op unless the current line is empty
return if rli.line? and not rli.line.match /^\s*$/
return if repl.line? and not repl.line.match /^\s*$/
# eval, print, loop
multiline.enabled = not multiline.enabled
rli.line = ''
rli.cursor = 0
rli.output.cursorTo 0
rli.output.clearLine 1
repl.line = ''
repl.cursor = 0
repl.output.cursorTo 0
repl.output.clearLine 1
# XXX: multiline hack
multiline.buffer = multiline.buffer.replace /\n/g, '\uFF00'
rli.emit 'line', multiline.buffer
repl.emit 'line', multiline.buffer
multiline.buffer = ''
else
multiline.enabled = not multiline.enabled
rli.setPrompt multiline.initialPrompt
rli.prompt true
repl.setPrompt multiline.initialPrompt
repl.prompt true
return
# Store and load command history from a file
@@ -139,17 +139,17 @@ addHistory = (repl, filename, maxSize) ->
fs.readSync readFd, buffer, 0, size, stat.size - size
fs.closeSync readFd
# Set the history on the interpreter
repl.rli.history = buffer.toString().split('\n').reverse()
repl.history = buffer.toString().split('\n').reverse()
# If the history file was truncated we should pop off a potential partial line
repl.rli.history.pop() if stat.size > maxSize
repl.history.pop() if stat.size > maxSize
# Shift off the final blank newline
repl.rli.history.shift() if repl.rli.history[0] is ''
repl.rli.historyIndex = -1
lastLine = repl.rli.history[0]
repl.history.shift() if repl.history[0] is ''
repl.historyIndex = -1
lastLine = repl.history[0]
fd = fs.openSync filename, 'a'
repl.rli.addListener 'line', (code) ->
repl.addListener 'line', (code) ->
if code and code.length and code isnt '.history' and code isnt '.exit' and lastLine isnt code
# Save the latest command in the file
fs.writeSync fd, "#{code}\n"
@@ -163,7 +163,7 @@ addHistory = (repl, filename, maxSize) ->
repl.commands[getCommandId(repl, 'history')] =
help: 'Show command history'
action: ->
repl.outputStream.write "#{repl.rli.history[..].reverse().join '\n'}\n"
repl.outputStream.write "#{repl.history[..].reverse().join '\n'}\n"
repl.displayPrompt()
getCommandId = (repl, commandName) ->
@@ -212,7 +212,7 @@ module.exports =
opts = merge replDefaults, opts
repl = nodeREPL.start opts
runInContext opts.prelude, repl.context, 'prelude' if opts.prelude
repl.on 'exit', -> repl.outputStream.write '\n' if not repl.rli.closed
repl.on 'exit', -> repl.outputStream.write '\n' if not repl.closed
addMultilineHandler repl
addHistory repl, opts.historyFile, opts.historyMaxInputSize if opts.historyFile
# Adapt help inherited from the node REPL

View File

@@ -5,7 +5,7 @@
# shorthand into the unambiguous long form, add implicit indentation and
# parentheses, and generally clean things up.
{throwSyntaxError} = require './helpers'
{throwSyntaxError, extractAllCommentTokens} = require './helpers'
# Move attached comments from one token to another.
moveComments = (fromToken, toToken) ->
@@ -53,11 +53,11 @@ exports.Rewriter = class Rewriter
@normalizeLines()
@tagPostfixConditionals()
@addImplicitBracesAndParens()
@addParensToChainedDoIife()
@rescueStowawayComments()
@addLocationDataToGeneratedTokens()
@enforceValidCSXAttributes()
@fixOutdentLocationData()
@enforceValidJSXAttributes()
@fixIndentationLocationData()
@exposeTokenDataToGrammar()
if process?.env?.DEBUG_REWRITTEN_TOKEN_STREAM
console.log 'Rewritten token stream:' if process.env.DEBUG_TOKEN_STREAM
console.log (t[0] + '/' + t[1] + (if t.comments then '*' else '') for t in @tokens).join ' '
@@ -118,14 +118,21 @@ exports.Rewriter = class Rewriter
# The lexer has tagged the opening bracket of an indexing operation call.
# Match it with its paired close.
closeOpenIndexes: ->
startToken = null
condition = (token, i) ->
token[0] in [']', 'INDEX_END']
action = (token, i) ->
token[0] = 'INDEX_END'
if @tokens.length >= i and @tokens[i + 1][0] is ':'
startToken[0] = '['
token[0] = ']'
else
token[0] = 'INDEX_END'
@scanTokens (token, i) ->
@detectEnd i + 1, condition, action if token[0] is 'INDEX_START'
if token[0] is 'INDEX_START'
startToken = token
@detectEnd i + 1, condition, action
1
# Match tags in token stream starting at `i` with `pattern`.
@@ -202,8 +209,8 @@ exports.Rewriter = class Rewriter
tokens.splice i, 0, generate 'CALL_END', ')', ['', 'end of input', token[2]], prevToken
i += 1
startImplicitObject = (idx, startsLine = yes) ->
stack.push ['{', idx, sameLine: yes, startsLine: startsLine, ours: yes]
startImplicitObject = (idx, {startsLine = yes, continuationLineIndent} = {}) ->
stack.push ['{', idx, sameLine: yes, startsLine: startsLine, ours: yes, continuationLineIndent: continuationLineIndent]
val = new String '{'
val.generated = yes
tokens.splice idx, 0, generate '{', val, token, prevToken
@@ -307,12 +314,15 @@ exports.Rewriter = class Rewriter
# if f(a: 1)
#
# which is probably always unintended.
# Furthermore dont allow this in literal arrays, as
# that creates grammatical ambiguities.
# Furthermore dont allow this in the first line of a literal array
# or explicit object, as that creates grammatical ambiguities (#5368).
if tag in IMPLICIT_FUNC and
@indexOfTag(i + 1, 'INDENT') > -1 and @looksObjectish(i + 2) and
not @findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH',
'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])
'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL']) and
not ((s = stackTop()?[0]) in ['{', '['] and
not isImplicit(stackTop()) and
@findTagsBackwards(i, s))
startImplicitCall i + 1
stack.push ['INDENT', i + 2]
return forward(3)
@@ -321,19 +331,31 @@ exports.Rewriter = class Rewriter
if tag is ':'
# Go back to the (implicit) start of the object.
s = switch
when @tag(i - 1) in EXPRESSION_END then start[1]
when @tag(i - 1) in EXPRESSION_END
[startTag, startIndex] = start
if startTag is '[' and startIndex > 0 and @tag(startIndex - 1) is '@' and not tokens[startIndex - 1].spaced
startIndex - 1
else
startIndex
when @tag(i - 2) is '@' then i - 2
else i - 1
startsLine = s <= 0 or @tag(s - 1) in LINEBREAKS or tokens[s - 1].newLine
# Are we just continuing an already declared object?
# Including the case where we indent on the line after an explicit '{'.
if stackTop()
[stackTag, stackIdx] = stackTop()
if (stackTag is '{' or stackTag is 'INDENT' and @tag(stackIdx - 1) is '{') and
(startsLine or @tag(s - 1) is ',' or @tag(s - 1) is '{')
stackNext = stack[stack.length - 2]
if (stackTag is '{' or
stackTag is 'INDENT' and stackNext?[0] is '{' and
not isImplicit(stackNext) and
@findTagsBackwards(stackIdx-1, ['{'])) and
(startsLine or @tag(s - 1) is ',' or @tag(s - 1) is '{') and
@tag(s - 1) not in UNFINISHED
return forward(1)
startImplicitObject(s, !!startsLine)
preObjectToken = if i > 1 then tokens[i - 2] else []
startImplicitObject(s, {startsLine: !!startsLine, continuationLineIndent: preObjectToken.continuationLineIndent})
return forward(2)
# End implicit calls when chaining method calls
@@ -357,6 +379,12 @@ exports.Rewriter = class Rewriter
break unless isImplicit stackItem
stackItem[2].sameLine = no if isImplicitObject stackItem
# End indented-continuation-line implicit objects once that indentation is over.
if tag is 'TERMINATOR' and token.endsContinuationLineIndentation
{preContinuationLineIndent} = token.endsContinuationLineIndentation
while inImplicitObject() and (implicitObjectIndent = stackTop()[2].continuationLineIndent)? and implicitObjectIndent > preContinuationLineIndent
endImplicitObject()
newLine = prevTag is 'OUTDENT' or prevToken.newLine
if tag in IMPLICIT_END or
(tag in CALL_CLOSERS and newLine) or
@@ -409,10 +437,10 @@ exports.Rewriter = class Rewriter
endImplicitObject i + offset
return forward(1)
# Make sure only strings and wrapped expressions are used in CSX attributes.
enforceValidCSXAttributes: ->
# Make sure only strings and wrapped expressions are used in JSX attributes.
enforceValidJSXAttributes: ->
@scanTokens (token, i, tokens) ->
if token.csxColon
if token.jsxColon
next = tokens[i + 1]
if next[0] not in ['STRING_START', 'STRING', '(']
throwSyntaxError 'expected wrapped or quoted JSX attribute', next[2]
@@ -426,6 +454,13 @@ exports.Rewriter = class Rewriter
tokens[method] generate 'TERMINATOR', '\n', tokens[j] unless tokens[j][0] is 'TERMINATOR'
tokens[method] generate 'JS', '', tokens[j], token
dontShiftForward = (i, tokens) ->
j = i + 1
while j isnt tokens.length and tokens[j][0] in DISCARDED
return yes if tokens[j][0] is 'INTERPOLATION_END'
j++
no
shiftCommentsForward = (token, i, tokens) ->
# Find the next surviving token and attach this tokens comments to it,
# with a flag that we know to output such comments *before* that
@@ -474,7 +509,7 @@ exports.Rewriter = class Rewriter
ret = shiftCommentsBackward dummyToken, i - 1, tokens
if token.comments.length isnt 0
shiftCommentsForward token, i, tokens
else
else unless dontShiftForward i, tokens
# If any of this tokens comments start a line—theres only
# whitespace between the preceding newline and the start of the
# comment—and this isnt one of the special `JS` tokens, then
@@ -504,58 +539,112 @@ exports.Rewriter = class Rewriter
@scanTokens (token, i, tokens) ->
return 1 if token[2]
return 1 unless token.generated or token.explicit
if token.fromThen and token[0] is 'INDENT'
token[2] = token.origin[2]
return 1
if token[0] is '{' and nextLocation=tokens[i + 1]?[2]
{first_line: line, first_column: column} = nextLocation
{first_line: line, first_column: column, range: [rangeIndex]} = nextLocation
else if prevLocation = tokens[i - 1]?[2]
{last_line: line, last_column: column} = prevLocation
{last_line: line, last_column: column, range: [, rangeIndex]} = prevLocation
column += 1
else
line = column = 0
token[2] =
first_line: line
first_column: column
last_line: line
last_column: column
rangeIndex = 0
token[2] = {
first_line: line
first_column: column
last_line: line
last_column: column
last_line_exclusive: line
last_column_exclusive: column
range: [rangeIndex, rangeIndex]
}
return 1
# `OUTDENT` tokens should always be positioned at the last character of the
# previous token, so that AST nodes ending in an `OUTDENT` token end up with a
# location corresponding to the last “real” token under the node.
fixOutdentLocationData: ->
@scanTokens (token, i, tokens) ->
return 1 unless token[0] is 'OUTDENT' or
(token.generated and token[0] is 'CALL_END') or
(token.generated and token[0] is '}')
prevLocationData = tokens[i - 1][2]
token[2] =
first_line: prevLocationData.last_line
first_column: prevLocationData.last_column
last_line: prevLocationData.last_line
last_column: prevLocationData.last_column
return 1
fixIndentationLocationData: ->
@allComments ?= extractAllCommentTokens @tokens
findPrecedingComment = (token, {afterPosition, indentSize, first, indented}) =>
tokenStart = token[2].range[0]
matches = (comment) ->
if comment.outdented
return no unless indentSize? and comment.indentSize > indentSize
return no if indented and not comment.indented
return no unless comment.locationData.range[0] < tokenStart
return no unless comment.locationData.range[0] > afterPosition
yes
if first
lastMatching = null
for comment in @allComments by -1
if matches comment
lastMatching = comment
else if lastMatching
return lastMatching
return lastMatching
for comment in @allComments when matches comment by -1
return comment
null
# Add parens around a `do` IIFE followed by a chained `.` so that the
# chaining applies to the executed function rather than the function
# object (see #3736)
addParensToChainedDoIife: ->
condition = (token, i) ->
@tag(i - 1) is 'OUTDENT'
action = (token, i) ->
return unless token[0] in CALL_CLOSERS
@tokens.splice doIndex, 0, generate '(', '(', @tokens[doIndex]
@tokens.splice i + 1, 0, generate ')', ')', @tokens[i]
doIndex = null
@scanTokens (token, i, tokens) ->
return 1 unless token[1] is 'do'
doIndex = i
glyphIndex = i + 1
if @tag(i + 1) is 'PARAM_START'
glyphIndex = null
@detectEnd i + 1,
(token, i) -> @tag(i - 1) is 'PARAM_END'
(token, i) -> glyphIndex = i
return 1 unless glyphIndex? and @tag(glyphIndex) in ['->', '=>'] and @tag(glyphIndex + 1) is 'INDENT'
@detectEnd glyphIndex + 1, condition, action
return 2
return 1 unless token[0] in ['INDENT', 'OUTDENT'] or
(token.generated and token[0] is 'CALL_END' and not token.data?.closingTagNameToken) or
(token.generated and token[0] is '}')
isIndent = token[0] is 'INDENT'
prevToken = token.prevToken ? tokens[i - 1]
prevLocationData = prevToken[2]
# addLocationDataToGeneratedTokens() set the outdents location data
# to the preceding tokens, but in order to detect comments inside an
# empty "block" we want to look for comments preceding the next token.
useNextToken = token.explicit or token.generated
if useNextToken
nextToken = token
nextTokenIndex = i
nextToken = tokens[nextTokenIndex++] while (nextToken.explicit or nextToken.generated) and nextTokenIndex isnt tokens.length - 1
precedingComment = findPrecedingComment(
if useNextToken
nextToken
else
token
afterPosition: prevLocationData.range[0]
indentSize: token.indentSize
first: isIndent
indented: useNextToken
)
if isIndent
return 1 unless precedingComment?.newLine
# We dont want e.g. an implicit call at the end of an `if` condition to
# include a following indented comment.
return 1 if token.generated and token[0] is 'CALL_END' and precedingComment?.indented
prevLocationData = precedingComment.locationData if precedingComment?
token[2] =
first_line:
if precedingComment?
prevLocationData.first_line
else
prevLocationData.last_line
first_column:
if precedingComment?
if isIndent
0
else
prevLocationData.first_column
else
prevLocationData.last_column
last_line: prevLocationData.last_line
last_column: prevLocationData.last_column
last_line_exclusive: prevLocationData.last_line_exclusive
last_column_exclusive: prevLocationData.last_column_exclusive
range:
if isIndent and precedingComment?
[
prevLocationData.range[0] - precedingComment.indentSize
prevLocationData.range[1]
]
else
prevLocationData.range
return 1
# Because our grammar is LALR(1), it cant handle some single-line
# expressions that lack ending delimiters. The **Rewriter** adds the implicit
@@ -612,13 +701,16 @@ exports.Rewriter = class Rewriter
tokens.splice i, 1, @indentation()...
return 1
if @tag(i + 1) in EXPRESSION_CLOSE
if token[1] is ';' and @tag(i + 1) is 'OUTDENT'
tokens[i + 1].prevToken = token
moveComments token, tokens[i + 1]
tokens.splice i, 1
return 0
if tag is 'CATCH'
for j in [1..2] when @tag(i + j) in ['OUTDENT', 'TERMINATOR', 'FINALLY']
tokens.splice i + j, 0, @indentation()...
return 2 + j
if tag in ['->', '=>'] and (@tag(i + 1) is ',' or @tag(i + 1) is '.' and token.newLine)
if tag in ['->', '=>'] and (@tag(i + 1) in [',', ']'] or @tag(i + 1) is '.' and token.newLine)
[indent, outdent] = @indentation tokens[i]
tokens.splice i + 1, 0, indent, outdent
return 1
@@ -661,6 +753,19 @@ exports.Rewriter = class Rewriter
@detectEnd i + 1, condition, action
return 1
# For tokens with extra data, we want to make that data visible to the grammar
# by wrapping the token value as a String() object and setting the data as
# properties of that object. The grammar should then be responsible for
# cleaning this up for the node constructor: unwrapping the token value to a
# primitive string and separately passing any expected token data properties
exposeTokenDataToGrammar: ->
@scanTokens (token, i) ->
if token.generated or (token.data and Object.keys(token.data).length isnt 0)
token[1] = new String token[1]
token[1][key] = val for own key, val of (token.data ? {})
token[1].generated = yes if token.generated
1
# Generate the indentation tokens, based on another token on the same line.
indentation: (origin) ->
indent = ['INDENT', 2]
@@ -690,6 +795,7 @@ BALANCED_PAIRS = [
['PARAM_START', 'PARAM_END']
['INDEX_START', 'INDEX_END']
['STRING_START', 'STRING_END']
['INTERPOLATION_START', 'INTERPOLATION_END']
['REGEX_START', 'REGEX_END']
]
@@ -713,11 +819,12 @@ IMPLICIT_FUNC = ['IDENTIFIER', 'PROPERTY', 'SUPER', ')', 'CALL_END', ']', 'IN
# If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
IMPLICIT_CALL = [
'IDENTIFIER', 'CSX_TAG', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN'
'IDENTIFIER', 'JSX_TAG', 'PROPERTY', 'NUMBER', 'INFINITY', 'NAN'
'STRING', 'STRING_START', 'REGEX', 'REGEX_START', 'JS'
'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS'
'DYNAMIC_IMPORT', 'IMPORT_META', 'NEW_TARGET'
'UNDEFINED', 'NULL', 'BOOL'
'UNARY', 'YIELD', 'AWAIT', 'UNARY_MATH', 'SUPER', 'THROW'
'UNARY', 'DO', 'DO_IIFE', 'YIELD', 'AWAIT', 'UNARY_MATH', 'SUPER', 'THROW'
'@', '->', '=>', '[', '(', '{', '--', '++'
]
@@ -747,9 +854,14 @@ CONTROL_IN_IMPLICIT = ['IF', 'TRY', 'FINALLY', 'CATCH', 'CLASS', 'SWITCH']
# `STRING_START` isnt on this list because its `locationData` matches that of
# the node that becomes `StringWithInterpolations`, and therefore
# `addDataToNode` attaches `STRING_START`s tokens to that node.
DISCARDED = ['(', ')', '[', ']', '{', '}', '.', '..', '...', ',', '=', '++', '--', '?',
'AS', 'AWAIT', 'CALL_START', 'CALL_END', 'DEFAULT', 'ELSE', 'EXTENDS', 'EXPORT',
'FORIN', 'FOROF', 'FORFROM', 'IMPORT', 'INDENT', 'INDEX_SOAK', 'LEADING_WHEN',
'OUTDENT', 'PARAM_END', 'REGEX_START', 'REGEX_END', 'RETURN', 'STRING_END', 'THROW',
'UNARY', 'YIELD'
DISCARDED = ['(', ')', '[', ']', '{', '}', ':', '.', '..', '...', ',', '=', '++', '--', '?',
'AS', 'AWAIT', 'CALL_START', 'CALL_END', 'DEFAULT', 'DO', 'DO_IIFE', 'ELSE',
'EXTENDS', 'EXPORT', 'FORIN', 'FOROF', 'FORFROM', 'IMPORT', 'INDENT', 'INDEX_SOAK',
'INTERPOLATION_START', 'INTERPOLATION_END', 'LEADING_WHEN', 'OUTDENT', 'PARAM_END',
'REGEX_START', 'REGEX_END', 'RETURN', 'STRING_END', 'THROW', 'UNARY', 'YIELD'
].concat IMPLICIT_UNSPACED_CALL.concat IMPLICIT_END.concat CALL_CLOSERS.concat CONTROL_IN_IMPLICIT
# Tokens that, when appearing at the end of a line, suppress a following TERMINATOR/INDENT token
exports.UNFINISHED = UNFINISHED = ['\\', '.', '?.', '?::', 'UNARY', 'DO', 'DO_IIFE', 'MATH', 'UNARY_MATH', '+', '-',
'**', 'SHIFT', 'RELATION', 'COMPARE', '&', '^', '|', '&&', '||',
'BIN?', 'EXTENDS']

Some files were not shown because too many files have changed in this diff Show More